Lärare: Markus Saers.
UPPSALA UNIVERSITET
Inst. f. lingvistik och filologi
Kurssidan
Uppsala universitet
Hoppa över länkar

Obligatorisk Inlämningsuppgift

Bakgrund

Inom språkteknologi behöver man ofta läsa in stora mängder text för att sedan behandla den på något sätt. Den här uppgiften går ut på att bygga ett grundläggande system för den här typen av databehandling.

På senare år har olika former av statistik över ordförekomster och likannde blivit ett vanligt arbetsredskap inom språkteknologi, särskilt för ord i sin kontext, som brukar modelleras med n-gram.

Data

För att lösa uppgiften tillhandahålls SUC i två förbehandlade format, ett med bara löpord:

smygrustning av raketvapen av Mats LundegÅrd DN:s korrespondent . London .
... samt ett med ordklasstaggade löpord:
smygrustning+NN av+PP raketvapen+NN av+PP Mats+PM LundegÅrd+PM DN:s+PM korrespondent+NN .+MAD London+PM .+MAD

Du hittar de två versionerna av korpusen nedan. Använd wget för att hämta dem, din webläsare kanske inte klarar av att visa alla 1 166 592 ord utan problem.

Uppgift

Bygg ett program som läser in Stockholm–Umeå-korpusen och sedan rapporterar olika sorters statistik om den.

Programmet ska kunna rapportera följande:

Ordet ”ord” i ”löpord” och ”ordtyp” ovan ska också kunna omtolkas till att betyda n-gram. Egentligen är ord-fallet 1-gram, och steget är med andra ord inte så långt till 2-gram, 3-gram, ..., n-gram. Programmet ska klara av att hantera godtyckliga värden på n. Kom dock ihåg att väldigt höga n-värden kan göra att programmet får slut på minne vid körning. Det ska dock vara byggt så att det kan hantera dessa i teorin.

Programmet ska vara möjligt att använda på ett praktiskt sätt från kommandoprompten. Det innebär bland annat att värdet på n ska kunna variers med en flagga. De olika statistiska mått som beräknas ska också kunna styras från kommandoprompten, antingen med flaggor till ett program, eller genom att du skriver flera program som gör olika saker.

För att läsa in och skriva ut kan du använda standard in och standard ut. Det gör att man kan ”pipea” in korpusen, och sedan ”pipea” ut resultatet från kommandoprompten. Om du vill kan du även bygga stöd för att läsa in ifrån och skriva ut till namngivna filer internt i Java, men det är inte nödvändigt. En viktig detalj är att inga filnamn får ”hårdkodas” i ditt program. Om du väljer att öppna namngivna filer måste dessa namn kommuniceras till programmet via kommandoprompten.

Om du väljer att lösa VG-uppgiften ska statistik kunna framställas för löpord, taggade löpord samt isolerade taggar.

Implementering

Implementationen ska vara skriven i Java, och följa en god programmeringsmetodik. Det innebär att problemet ska lösas en del i taget, och att lämpliga klasser skapas för att lösa delproblemen. De klasser som skapas bör vara adekvat inkapslade, och visa så lite som möjligt utåt. En god uppdelning betyder att du int ebehöver skriva samma programsnutt flera gånger.

Din implementation ska lämnas in i ett sådant skick att jag kan testköra den. Du kan göra detta genom att packa ihop filerna i en tar-boll, zip-fil, jar-fil eller liknande och sedan e-posta den till mig, eller genom att skapa en katalog på stp-nätverket, och se till att jag har läsrättigheter i den katalogen. I så fall räcker det med att e-posta sökvägen till katalogen.

Dokumentering

För att dokummentera programmet ska alla klasser förses med adekvat dokumentationskommentering. Allt som deklareras med public ska ha en sådan kommentar som beskriver intentionen du haft med att skapa klassen/metoden/variabeln samt varför den finns tillgänglig.

En dokumentationssida ska skapas med programmet javadoc, och göras tillgänglig som en del av examinationen.

Inlämning

Inlämning ska ske genom att implementationen görs tillgänglig för mig, dokumentationen publiceras så att den går att komma åt på nätet, samt att ett e-postmeddelande skickas till mig med information om hur och var jag kommer åt just din lösning. Din lösning ska vara mig tillhanda senast 7 juni 2009.

Examination

För betyget G krävs att uppgiften löses på ett tillfredsställande sätt med löpordsversionen av SUC. För betyget VG krävs samma sak för den ordklasstaggade versionen.

Referenser

Klasser som är bra att ha i åtankarna vid lösandet av denna uppgift:

Exempel

Här är ett exempel på vilken typ av output jag förväntar mig av era program.

Jag använder testkorpusen test.txt:

får får får ? nej får får inte får , får får lamm !

Mitt program har totalt 6 klasser, och den klass som är körbar heter CorpusReader. Just nu skriver den ut både statistiken och frekvensordlistan, mest för att det ger en idé om vad det ska klara av. Ni bör implementera något sätt att skilja dem åt. Jag har valt att skriva ut frekvensordlistan i formatet frekvens-tab-ord, vilket gör att man enkelt kan sortera orden i frekvensordning när de väl lagts i en fil. För att skriva ut en tabulator (ett tecken som ser ut som (oftast) 8 mellanslag), använd "\t".

Här är lite exempel på hur det kan användas (vad jag skrivit vid kommandoraden, och vad programmet skriver ut):

markuss@objekt$ java CorpusReader 1 < test.txt Types: 7 Tokens: 14 Type/Token-ratio: 0.5 1 nej 1 ! 1 lamm 1 ? 8 får 1 inte 1 , markuss@objekt$ java CorpusReader 2 < test.txt Types: 10 Tokens: 13 Type/Token-ratio: 0.7692307692307693 1 får , 4 får får 1 inte får 1 får inte 1 lamm ! 1 , får 1 får ? 1 får lamm 1 ? nej 1 nej får markuss@objekt$ java CorpusReader 3 < test.txt Types: 12 Tokens: 12 Type/Token-ratio: 1.0 1 ? nej får 1 får inte får 1 får får ? 1 inte får , 1 får får lamm 1 får ? nej 1 får får får 1 får , får 1 får lamm ! 1 nej får får 1 , får får 1 får får inte markuss@objekt$

Jag har också en version som klarar av en taggad version av testkorpusen (ska lösas för VG). Så här ser testkorpusen test.tgd ut:

får+VB får+NN får+NN ?+MAD nej+ADV får+NN får+VB inte+NEG får+NN ,+MID får+NN får+VB lamm+NN !+MAD

Och så här ser körexemplet ut:

markuss@objekt$ java CorpusReader 1 < test.tgd Types: 8 Tokens: 14 Type/Token-ratio: 0.5714285714285714 1 ?+MAD 1 nej+ADV 1 inte+NEG 3 får+VB 5 får+NN 1 lamm+NN 1 ,+MID 1 !+MAD markuss@objekt$ java CorpusReader 2 < test.tgd Types: 12 Tokens: 13 Type/Token-ratio: 0.9230769230769231 1 får+VB lamm+NN 1 nej+ADV får+NN 1 får+VB inte+NEG 1 får+VB får+NN 1 inte+NEG får+NN 1 får+NN får+NN 1 ?+MAD nej+ADV 1 får+NN ?+MAD 1 ,+MID får+NN 2 får+NN får+VB 1 får+NN ,+MID 1 lamm+NN !+MAD markuss@objekt$ java CorpusReader 3 < test.tgd Types: 12 Tokens: 12 Type/Token-ratio: 1.0 1 ,+MID får+NN får+VB 1 inte+NEG får+NN ,+MID 1 ?+MAD nej+ADV får+NN 1 får+VB får+NN får+NN 1 får+VB lamm+NN !+MAD 1 får+NN ,+MID får+NN 1 nej+ADV får+NN får+VB 1 får+NN får+VB lamm+NN 1 får+VB inte+NEG får+NN 1 får+NN får+VB inte+NEG 1 får+NN ?+MAD nej+ADV 1 får+NN får+NN ?+MAD markuss@objekt$

I VG-uppgiften ingick också att göra samma sak för isolerade ord, samt för isolerade taggar. Jag har löst det så att man kan skriva orden token respektive tag efter värdet på n för att välja bara ord respektive bara taggar. Då se rdet ut såhär:

markuss@objekt$ java CorpusReader 2 token < test.tgd Types: 10 Tokens: 13 Type/Token-ratio: 0.7692307692307693 1 får , 4 får får 1 inte får 1 får inte 1 lamm ! 1 , får 1 får ? 1 får lamm 1 ? nej 1 nej får markuss@objekt$ java CorpusReader 2 tag < test.tgd Types: 10 Tokens: 13 Type/Token-ratio: 0.7692307692307693 1 NN NN 1 NN MID 1 NEG NN 2 NN MAD 1 MAD ADV 2 NN VB 1 MID NN 1 ADV NN 2 VB NN 1 VB NEG markuss@objekt$