« En liten undersökning om kuluriga ord | Main | Word Meld Simple - en etyd med Ajax-tekniken »

januari 23, 2006

Något om prefixträd sorterade på lite olika sätt samt komprimering

Av en privat (och personlig) orsak behövdes ett program för att skapa unika prefix av ord i en lista, och sedan att presentera dessa prefix som ett träd. Anledningen var ungefär att korta ner en lista av ord till kortare ord (dess prefix).

Ett exempel på ett sådant prefixträd är för de svenska månadsnamnen:

a:
  ap: april
  au: augusti
d: december
f: februari
j:
  ja: januari
  ju:
    jul: juli
    jun: juni
m:
  ma:
    maj: maj (!!!)
    mar: mars
n: november
o: oktober
s: september

Här ser vi t.ex. att månadsnamnen december, februari och november kan komprimeras till en enda bokstav, medan april och augusti båda börjar på bokstaven a så vi måste här ta till en extra bokstav för att skilja dem åt. Man kan också notera att maj inte blev något prefix alls, utan här behövs hela ordet eftersom mars, den rackaren, ligger och stör. Sådana fall markeras med !!!!


Program Prefix Trees
Det har naturligtvis skapats ett program för att kunna leka vidare med sådana här ord-listor, och som - möjligen något missledande - kallas för Prefix trees.


Programkörningen för ovanstående svenska månadsnamen finns ungefär här.


Komprimering och annat skoj
Även om det primära syftet med programmet var att skapa unika prefix och prefixträd så var det svårt att låta bli att studera vissa saker i mer detalj.

Om man kör programmet för de svenska månadsnamnet kommer det, förutom det fina prefixträdet, även lite statistik (längst ner på sidan):

...
Original total length of words: 74
Total length of prefixes: 23
Mean prefix length: 1.92
Compression factor (original length/prefix length): 3.217

Man kan bl.a. se att det medellängden av de skapade prefixen är 1.92, vilket ska jämföras med medellängden av de ursprungliga orden på 6.17. Komprimeringsfaktorn är 3.217, vilket räknas ut med formeln

(sammanlagda längden av original orden) / (sammanlagda längden av prefixerna)

Dvs: genom att använda de unika prefixen istället för de hela orden sparar man en hel del, t.ex. träd (sic!) om man skulle använda papper för att skriva dem. Det kanske blir svårt att läsa det, men man skulle kunna spara både tid och pengar på detta. Nedan kommer vi att studera hur man kan spara något mer tid/papper/pengar men i gengäld blir det i stort sett oläsbart...


Frekvenssortering av bokstäver
En finess med programmet är att man kan studera lite olika varianter av representation av orden innan det skapas prefix. T.ex.

Sedan den mest intressanta varianten: bokstavsfrekvenssortering (valet Sort by letter frequency, som innebär att innan man skapar prefixen sorterar man ordets bokstäver i ordning av hur vanliga/sällsynta bokstäverna är bland samtliga ords bokstäver. T.ex. så är det troligt att bokstaven "z" är sällsynt vilket gör att ett ord med "z" kommer att prefixas som z + eventuellt någon annan bokstav.

Om vi fortsätter med månadsnamnsexemplet får man med bokstavsfrekvenssortering följande prefixträd:

d: december
f: februari
g: augusti
j: maj
k: oktober
l: juli
n:
  nj:
    nju:
      njui: juni
        njuia: januari
p:
  pl: april
  ps: september
s: mars
v: november
....
Original total length of words: 74
Total length of prefixes: 21
Mean original length: 6.17
Mean prefix length: 1.75
Compression factor (original length/prefix length): 3.524

Om man jämför med det "vanliga" prefixträdet så är komprimeringsfaktorn något lägre för bokstavsfrekvenssorteringsvarianten (3.524 jämfört med 3.217).

Denna skillnad tenderar att vara beständigt: Detta innebär att om man använder bokstavsfrekvenser istället blir det något bättre komprimering. Nackdelen är naturligtvis att "förkortningen" (prefixet) är fullständigt obegriplig. Se även en mer systematisk genomgång nedan.

Några noter kring detta
Möjligen skulle man här kunna göra en analogi med Huffman-kodning (ref till en.wikiedia) som skapar binära koder efter bokstävernas frekvens, där den kortaste koden tilldeleas den vanligaste bokstaven etc.

En mer avancerad variant av prefixträd skulle vara att analysera prefixträdet för att komprimera det ännu mer.

Det går naturligtvis också att göra det väldigt enkelt för sig och koda varje ord till ett eller flera fullständigt slumpmässiga tecken alltefter ordens/bokstävernas frekvens i texten. Men det är en övning som lämnas åt vidare öden (eller övning åt läsaren/skribenten).

Den ursprungliga poängen med prefixträden var att de skulle vara lätta att skapa och (relativt) lätt att uttyda när man ser dem. När man använder sorteringar av olika slag förloras detta syfte bort i skymningen varvid endast nästa dags solstrålar är glada att se det.


Liten undersökning
Det gjordes också en undersökning hur antalet olika ord i listan påverkar komprimeringsfaktorn respektive medelprefixlängden. Detta gjordes för ett olika antal slupmässiga svenska ord (ur en ordlista på nästan 400000 ord).

Det visar sig - inte speciellt förvånande - att ju fler slumpmässiga ord listan innehåller, desto sämre blir komprimeringsfaktorn och desto längre blir medellängden på prefixen. Som variansen visar är det relativt stabila värden förutom för den första körningen (10 ord i listan). Av tidsskäl kördes endast 10 gånger med samma liststorlek.

Prefix utan någon bokstavssortering

Antal ordKomprimeringsgradKomprimeringsgrad variansPrefix medellängdPrefix medellängd, varians
107.807304.675261.470000.12456
1004.140800.028742.637000.00842
2003.548600.035303.115000.01812
5003.042600.002013.608000.00775
10002.705900.001994.102000.00368
20002.399400.000784.602000.00717
30002.236200.000634.960000.00207
50002.068100.000305.364000.00158
100001.845000.000095.998000.00057
200001.654000.000026.688000.00040
500001.440400.000017.680000.00031
1000001.315200.000008.413000.00020

Prefix med frekvensbokstavssortering

Antal ordKomprimeringsgradKomprimeringsgrad variansPrefix medellängdPrefix medellängd, varians
109.688304.153061.150000.02500
1004.244700.026752.568000.01280
2003.819100.021282.948000.00544
5003.265200.001933.409000.00283
10002.893400.003513.835000.00372
20002.618100.000324.242000.00044
30002.471300.000824.489000.00159
50002.287800.000184.821000.00054
100002.064800.000095.362000.00042
200001.873100.000035.910000.00018
500001.650100.000016.708000.00008
1000001.507100.000007.344000.00014


Andra exempel
Jag har även kört programmet på några andra exempel, t.ex. 1000 vanligaste svenska orden, svenska förnamnen samt svenska efternamnen (plus "Kjellerstrand") från Språkbanken:


Se även
En möjlig variant att göra en komprimering eller på annat sätt förkorta saker och ting är att använda reguljära uttryck, t.ex. som i programmet MakeRegex,.

Posted by hakank at januari 23, 2006 10:51 EM Posted to Program | Språk | Statistik/data-analys

Comments

Hej Håkan!
Jag hade väntat mig en rak lista på tusen
vanligaste ord.
Intressant med bokstavsfrekventering.
Jag har en intressant sträng om listan.
Skulle du kunna lägga till en sådan någonstans?
Hälsningar
Mike

Posted by: mike at december 1, 2007 03:16 EM

Mike:
På Språkbanken (som länkas till i sista avsnittet) finns ett flertal sådana listor. Direktlänken är
http://spraakbanken.gu.se/lb/statistik/margin.html

En annan representation av denna data finns även här:
http://spraakbanken.gu.se/pub/statistik/

Posted by: Håkan Kjellerstrand at december 1, 2007 10:29 EM