IN1140 H2019 gruppeoppgaver Språkmodeller og Ordklasser

Like dokumenter
IN1140 H2018 gruppeoppgaver Sannsynlighet og språkmodeller

INF1820: Introduksjon til språk-og kommunikasjonsteknologi

INF1820: Introduksjon til språk-og kommunikasjonsteknologi

PGZ - Hangman Ekspert Python Lærerveiledning

LF - Eksamen i INF1820

Øvingsforelesning 1 Python (TDT4110)

Hash-funksjoner. Introduksjon. Steg 1: Strekkoder. Eksempel. Skrevet av: Martin Strand

Løse reelle problemer

Prøveeksamen IN1000. IN Prøveeksamen. Dato november 2017 Tid 12:30-12:00 Alle trykte og skrevne hjelpemidler er tillatt.

INF120: Oblig 3. Yngve Mardal Moe

MENGDER (SETS) Læringsmål og pensum. Kapittel 9.2

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

TDT4110 Informasjonsteknologi grunnkurs: Tema: Dictionaries og mengder (sets) - Kapittel 9. Professor Alf Inge Wang

Python: Oppslagslister (dictionaries) og mengder 3. utgave: Kapittel 9

Informasjon Prøveeksamen i IN1000 høsten 2018

Mål. Pensum. TDT4110 Informasjonsteknologi grunnkurs: Tema: Dictionaries og sets (mengder) Utgave 3: Kap. 9. Terje Rydland - IDI/NTNU

Kryptering med vigenere-metoden


UNIVERSITETET I OSLO

Kondisjonstest. Algoritmer og datastrukturer. Python-oppgaver. Onsdag 6. oktober Her er noen repetisjonsoppgaver i Python.

2 Om statiske variable/konstanter og statiske metoder.

Håndtere mange verdier

Steg 1: Regneoperasjoner på en klokke

Informasjon Eksamen i IN1000 høsten 2017

INF1000 Eksamen 2014 (modifisert)

UNIVERSITETET I OSLO

Repetisjon Novice Videregående Python PDF

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

Eksamensoppgaver 2014

Objektorientert programmering i Python. Resten av semesteret. Innhold uke 9 Mer komplekse strukturer. Referanser og objekter, inkl Mentimeter spørsmål

INF 2820 V2015: Obligatorisk innleveringsoppgave 3

Python: Løkker. TDT4110 IT Grunnkurs Professor Guttorm Sindre

Fra Python til Java, del 2

INF1000 Eksamen 2014 (modifisert)

I dag skal vi ved hjelp av ganske enkel Python-kode finne ut om det er mulig å tjene penger på å selge og kjøpe en aksje.

Skilpaddetekst. Steg 1: Tekst på flere linjer. Sjekkliste. Introduksjon

EKSAMENSOPPGAVE / EKSAMENSOPPGÅVE

UNIVERSITETET I OSLO

Steg 1: Tekst på flere linjer

Tell sekunder. Introduksjon. Skrevet av: Teodor Heggelund. I denne oppgaven skal vi lage vårt eget spill!

EKSAMENSOPPGAVE / EKSAMENSOPPGÅVE

Legg bort skilpaddene dine, i dag skal vi lære hvordan vi kan sende hemmelige beskjeder!

Oblig 4 Undervisningshefte i grunnleggende JavaScript programmering

IN2110 Obligatorisk innlevering 1a

Øvingsforelesning 9 i Python (TDT4110)

Tre på rad mot datamaskinen. Steg 1: Vi fortsetter fra forrige gang. Sjekkliste. Introduksjon

JS: Grunnleggende JavaScript Nybegynner

2 Om statiske variable/konstanter og statiske metoder.

Øvingsforelesning 5 Python (TDT4110)

Objektorientert programmering i Python

Hangman. Steg 1: Velg et ord. Steg 2: Gjett en bokstav. Sjekkliste. Sjekkliste. Introduksjon

Hvordan løse problemer med programmering?

Innhold uke 9. Objektorientert programmering i Python. Om ukens pensum. Referanser og objekter Tema: Mer komplekse strukturer

Kryptering med Vigenère-metoden

Tre på rad mot datamaskinen. Steg 1: Vi fortsetter fra forrige gang

TDT4110 IT Grunnkurs Høst 2014

TDT4110 Informasjonsteknologi grunnkurs: Tema: Mer om strenger. - 3rd edition: Kapittel 8. Professor Alf Inge Wang

Metoder med parametre, løkker og arrayer

Legg bort skilpaddene dine, i dag skal vi lære hvordan vi kan sende hemmelige beskjeder!

MAT1030 Plenumsregning 1

Dokument-embeddings / Markov-kjeder. Fredrik Jørgensen, Schibsted Media/UiO

Steg 1: Rest etter divisjon

if-tester Funksjoner, løkker og iftester Løkker og Informasjonsteknologi 2 Læreplansmål Gløer Olav Langslet Sandvika VGS

INF 2820 V2018: Innleveringsoppgave 1

Kap 2: Løkker og lister

Øvingsforelesning 5 Python (TDT4110)

Oppsummering Assemblerkode Hopp Multiplikasjon Kode og data Array Oppsummering

UNIVERSITETET I OSLO

Plenumsregning 1. Kapittel 1. Roger Antonsen januar Velkommen til plenumsregning for MAT1030. Repetisjon: Algoritmer og pseudokode

I denne oppgaven skal vi repetere litt Python-syntaks, det er en god blanding av alle tingene du har lært i Python til nå.

ToPlayer. Steg 1: Kom i gang med metodene setup og draw. Gjør dette: Introduksjon:

Plenumsregning 1. MAT1030 Diskret Matematikk. Repetisjon: Algoritmer og pseudokode. Velkommen til plenumsregning for MAT1030

UNIVERSITETET I OSLO

MAT1030 Diskret Matematikk

Mål. Pensum. TDT4110 Informasjonsteknologi grunnkurs: Tema: Unntak (exceptions) (Kap 6) Dictionaries (Kap. 9) Terje Rydland - IDI/NTNU

Velkommen til plenumsregning for MAT1030. MAT1030 Diskret matematikk. Repetisjon: Algoritmer og pseudokode. Eksempel fra boka. Eksempel

I denne oppgaven skal vi gjøre enkle operasjoner på tekst, som å endre størrelsen på bokstavene og telle ord.

IN1000 Obligatorisk innlevering 7

JS: Grunnleggende JavaScript

For å sjekke at Python virker som det skal begynner vi med å lage et kjempeenkelt program. Vi vil bare skrive en enkel hilsen på skjermen.

Først må vi få datamaskinen til å velge et tilfeldig ord, så la oss begynne. Lagre programmet ditt og kjør det. Hvilket ord skrives ut?

EGENDEFINERTE FUNKSJONER I SAS OG LITT OM OPEN SOURCE INTEGRASJON SAS FANS I STAVANGER , MARIT FISKAAEN (SAS INSTITUTE)

Hangman. Level. Introduksjon

TDT4110 Informasjonsteknologi grunnkurs: Tema: Funksjoner med retur og moduler Utgave 3: Kap

Tell sekunder. Steg 0: Hva er forskjellig fra før? Introduksjon. I denne oppgaven skal vi lage vårt eget spill!

MAT1030 Diskret matematikk

Oppsummering fra sist

TDT4110 Informasjonsteknologi grunnkurs: Tema: Funksjoner med retur og moduler. - 3rd edition: Kapittel Professor Alf Inge Wang

TDT4110 IT Grunnkurs Høst 2014

UNIVERSITETET I OSLO

Kondisjonstest. Algoritmer og datastrukturer. Python-oppgaver - LF. Onsdag 6. oktober Her er noen repetisjonsoppgaver i Python.

Forside. 1 Hva skrives ut?

Forkurs INF1010. Dag 3. Andreas Færøvig Olsen Gard Inge Rosvold Institutt for Informatikk, 15.

ToPlayer. Introduksjon: Skrevet av: Ruben Gjerstad Eide og Kine Gjerstad Eide

Læringsmål og pensum. if (be): else (not_to_be):

UNIVERSITETET I OSLO

INF1820: Introduksjon til språk-og kommunikasjonsteknologi

INF1820: Introduksjon til språk-og kommunikasjonsteknologi

TDT4102 Prosedyre og Objektorientert programmering Vår 2015

TDT4105 Informasjonsteknologi, grunnkurs (ITGK)

Transkript:

IN1140 H2019 gruppeoppgaver Språkmodeller og Ordklasser 1 NLTK og språkmodeller Målet med denne oppgaven er å programmere to språkmodeller (en unigrammodell og trigrammodell) ved hjelp av Python s Natural Language Tool Kit (NLTK). Vi skal fokusere på følgende punkter: Fa tilgang til korpora i NLTK. Beregne frekvensdistribusjoner. Beregne sannsynligheter fra frekvensdistribusjonen. Bruke språkmodellen til å beregne unigram/trigram-sannsynligheter. Bruke en språkmodell til å generere tekst. Det er viktig at du jobber deg gjennom følgende steg, og at du forstår hva som skjer ved hvert steg. 1.1 NLTK Natural Language Tool Kit (NLTK) er en Python modul som brukes til å skrive programmer for språkprossessering. NLTK gir tilgang til både korpora og innebygde metoder. For mer informasjon om NLTK, besøk: http://www.nltk.org/. NLTK er installert på IFIs servere. Dersom du ønsker å installere det på egen maskin er det instruksjoner på NLTK-siden under Installing NLTK. For å kunne bruke NLTK i koden din, kan den importeres slik: import nltk Som nevnt tidligere, gir NLTK tilgang til en del korpora. For eksempel Gutenberg-korpuset som inneholder en rekke eldre bøker, Brown-korpuset inneholder romaner, noveller og nyhetesartikler, Reuters-korpuset inneholder nyheter, og Inaugural Address-korpuset som inneholder amerikanske presidenter sine innledende taler (fra 1789 til 2009). Hvert korpus inneholder et visst antall tekster. Du kan lese mer om dette her https://www.nltk.org/book/ch02.html. I denne omgang skal vi jobbe med Inaugural-korpuset. For å kunne laste ned dette korpuset, skriver du følgende: import nltk from nltk.corpus import inaugural For å liste alle dokumentene som finnes i korpuset kan du kjøre: print(inaugural.fileids()) Vi skal nå fokusere på Obama sin innledende tale fra 2009. Vi kan enkelt få tilgang til både teksten (ved bruk av raw), ordene (ved bruk av words) og setningene (ved bruk av sents) av talen:

inaugural.raw("2009-obama.txt") inaugural.words("2009-obama.txt") inaugural.sents("2009-obama.txt") Spørsmål 1: Skriv ut ordene og setningene i Obamas tale. Hva slags datastruktur (f.eks. streng, liste, ordbok) brukes for å representere ordene i talen? Hva med setningene? Vi lagrer ordene i talen i en variabel (obama_words). Vi kan deretter finne totalt antall ord (tokens) i talen slik: obama_words = inaugural.words("2009-obama.txt") total_words = len(obama_words) For å finne totalt antall distinkte ord (typer) gjør vi om ordene til små bokstaver og lagrer dem i en liste (distinct_words) som vi deretter sjekker lengden på: distinct_words = [] for w in obama_words: distinct_words.append(w.lower()) total_distinct_words = len(set(distinct_words)) Spørsmål 2: Hvor mange tokens og typer inneholder Obamas tale? Hvorfor har vi gjort om listen til en mengde (set)? Hva skjer dersom vi ikke gjør det? 1.2 Frekvensdistribusjon En frekvensdistribusjon registrerer antall ganger hvert utfall av et eksperiment har skjedd. For eksempel kan en frekvensdistribusjon brukes til å beregne antall ganger hvert ord forekommer i et dokument. Vi har sett tidligere at vi enkelt kan få tilgang til alle ordene i korpuset ved bruk av words. For å beregne frekvensdistribusjonen av hvert ord skal vi bruke Counter. En Counter er en modul som holder styr på hvor mange ganger ekvivalente verdier legges til. Counter må importeres før bruk slik: from collections import Counter For å beregne frekvensdistribusjonen av ordene i talen til Obama kan du gjøre slik: fd_obama_words = Counter(obama_words) Nå kan vi skrive ut de 50 mest frekvente ordene i talen slik: print("most common words: ",fd_obama_words.most_common(50)) Vi kan også enkelt finne ut hvor mange ganger visse ord forekommer i talen, for eksempel ordene peace, America og america : print("frequency of peace : ",fd_obama_words["peace"]) print("frequency of America : ",fd_obama_words["america"]) print("frequency of america : ",fd_obama_words["america"]) Sannsynligheten for en setning kan beregnes ved bruk av relativ frekvens i et korpus (se forelesningsnotater). Her antar vi at forekomster av ord er uavhengige, noe som ikke stemmer i virkeligheten, men som vi likevel skal teste her. Da skal vi ta i bruk totalt antall ord (tokens) som vi har regnet ut tidligere og lagre sannsynligheten for hvert ord i en ordbok (probabilities) der ordet er nøkkel og sannsynligheten er verdi:

probabilities = {} for word, count in fd_obama_words.items(): probabilities[word] = count/total_words Spørsmål 3: Ordboken probabilities inneholder sannsynligheten for ulike ord i teksten. Hva er nøkkel og hva er verdi i ordboken? Sannsynlighetene for alle mulige utfall summerer til (tilnærmet) 1, det kan vi sjekke ved å gjøre: print(sum(probabilities.values())) Vi kan nå generere en tekst basert på en slik sannsynlighetsberegning. Vi skal her benytte oss av NumPy, et Python-bibliotek for ulike typer matematiske beregninger. Vi skal benytte oss av random.choice fra NumPy, som tar inn en liste med ord og deres sannsynligheter og velger et angitt antall vilkårlige ord basert på den angitte sannsynlighetsdistribusjonen. For eksempel: >>> import numpy as np >>> aa_milne_arr = [ pooh, rabbit, piglet, Christopher ] >>> np.random.choice(aa_milne_arr, 5, p=[0.5, 0.1, 0.1, 0.3]) array([ pooh, pooh, pooh, Christopher, piglet ]) Vi sender ordene og sannsynlighetene vi beregnet for Obama-talen til random.choice som genererer (og skriver ut) en tekst på 20 ord slik: text = np.random.choice(list(probabilities.keys()), 20, p=list(probabilities.values())) print(text) Som du kan se, er den genererte teksten ikke veldig koherent. Den produserte teksten følger bare frekvensdistribusjonen i korpuset og ingenting mer. Nå som vi allerede har sannsynligheten for alle ordene, kan vi beregne sannsynligheten for en tekst. Fordi ordene er generert basert på at forekomster av ord er uavhengige, trenger vi kun å multiplisere alle sannsynlighetene sammen. Her benytter vi oss av NumPys prod-funksjon som multipliserer sammen alle tall i en liste (i dette tilfellet listen som inneholder sannsynligheten for hvert av ordene i teksten): word_probabilities = [] for w in text: word_probabilities.append(probabilities[w]) print(np.prod(word_probabilities)) 1.3 Språkmodeller En språkmodell tilordner en sannsynlighet for en ordsekvens ved bruk av en sannsynlighetsfordeling. Språkmodeller har mange applikasjoner i språkteknologi. For eksempel, i talegjenkjenning kan de bli brukt til å forutsi det neste uttalte ordet. I følgende steg, skal vi prøve å lage en trigramsmodell. Som nevnt tidligere, vi kan enkelt lese alle setningene i talen til Obama ved å bruke sents: obama_sents = inaugural.sents("2009-obama.txt") Forå lese kun første setning kan du gjøre: first_sentence = obama_sents[0] print(first_sentence) Det er enkelt å hente ut bigrammer og trigrammer i en tekst ved bruk av NLTK. Det eneste du trenger å gjøre er følgende:

from nltk import bigrams, trigrams print(list(bigrams(first_sentence))) print(list(trigrams(first_sentence))) Som du kan se, er ikke setningsbegynnelse og setningsslutt markert. For å inkludere denne informasjonen i bigrammmene og trigrammene dine kan du angi følgende: print(list(bigrams(first_sentence, pad_left=true, pad_right=true))) print(list(trigrams(first_sentence, pad_left=true, pad_right=true))) Spørsmål 4: Inspisér resultatet av forrige kall. Hvordan skiller disse bi- og trigrammene seg fra de forrige? Vi skal bruke disse trigrammene for å trene en språkmodell. For å gjøre det, skal vi bruke en ordbok som skal initialiseres med en defaultdict. defaultdict fungerer akkurat som en vanlig dictionary( ordbok ), men den initialiseres med en funksjon ( default factory ) som ikke tar noen argumenter og gir standardverdien for en ikke-eksisterende nøkkel. En defaultdict vil aldri heve en KeyError. En hvilken som helst nøkkel som ikke eksisterer får verdien returnert av default factory. For å kunne bruke defaultdict må vi importere den. Ta for deg følgende eksempel for å forstå hva en defaultdict er: >>> from collections import defaultdict >>> muffins = defaultdict(lambda: "Vanilje") >>> muffins["ida"] = "Blåbær" >>> muffins["stian"] = "Pecan nøtter" >>> muffins["ida"] Blåbær >>> muffins["pedro"] Vanilje Nå skal vi begynne å bygge modellen vår. La oss begynne med trigramsmodellen. Det første som må gjøres er å initialisere to defaultdict: from collections import defaultdict trigram_counts = defaultdict(lambda: defaultdict(lambda: 0)) trigram_model = defaultdict(lambda: defaultdict(lambda: 0.0)) Vi skal nå fylle ordboken trigram_counts med trigrammene i Obama-talen og antall forekomster: for sentence in obama_sents: for w1, w2, w3 in trigrams(sentence, pad_right=true, pad_left=true): trigram_counts[(w1, w2)][w3] += 1 Spørsmål 5: Ordboken trigram_counts inneholder tellinger for ulike trigrammer i teksten. Hva slags datastruktur er dette? Hva er nøkkel og hva er verdi i ordboken? Nå er trigrammene våre i en ordbok, og vi får enkel tilgang til elementene: print(trigram_counts["my", "fellow"]["citizens"]) print(trigram_counts["my", "fellow"]["nonexistingword"]) print(trigram_counts[none, None]["The"]) Spørsmål 6: I oppgave 2 jobbet vi med å beregne sannsynligheter til en bigrammodell. Hvordan gjør vi det samme for en trigrammodell? Vi skal nå beregne sannsynligheter for trigrammene våre og samle disse i ordboken trigram_model. Som vi vet trenger vi frekvensen for et trigram (total_trigramcount) samt frekvensen for de

toførste ordene i trigrammet (trigram_counts[w1_w2].values()) for å beregne sannsynligheten for et trigram: for w1_w2 in trigram_counts: total_trigramcount = sum(trigram_counts[w1_w2].values()) for w3 in trigram_counts[w1_w2]: trigram_model[w1_w2][w3] = trigram_counts[w1_w2][w3]/total_trigramcount La oss nå sjekke verdiene av de forrige testene: print(trigram_model["my", "fellow"]["citizens"]) print(trigram_model["my", "fellow"]["nonexistingword"]) print(trigram_model[none, None]["The"]) Nå skal vi trene selve modellen. Vi tar i bruk en variabel (sentence_is_finished) med boolsk verdi for å sjekke om den produserte teksten har nådd ønsket lengde. Vi begynner med å lage en tuppel (i dette tilfellet et par) av de to siste elementene i listen (altså variabelen text) ved å si tuple(text[-2:]). Dette er bigrammet som danner konteksten for ordet som skal genereres. Deretter slår vi opp i trigrammodellen vår for å finne alle mulige tredje ord i henhold til modellen og deres sannsynligheter. random.choice genererer deretter neste ord basert på denne sannsynlighetsdistribusjonen: text = [None, None] sentence_is_finished = False while not sentence_is_finished: key = tuple(text[-2:]) words = list(trigram_model[key].keys()) probs = list(trigram_model[key].values()) text.append(np.random.choice(words, p=probs)) if text[-2:] == [None, None]: sentence_is_finished = True print(.join([t for t in text if t])) Spørsmål 7: Hvorfor initialiseres text-listen med [None, None]? Og hvorfor brukes samme bigram som test på at setningen er ferdig? Gratulerer! Da har du laget din første trigramsmodell som produserer tekst. Som du ser gir trigrammodellen en mye bedre og mer sammenhengende tekst enn unigrammodellen i den tidligere oppgaven. Spørsmål 8: Hvordan kan vi beregne sannsynligheten til teksten vi nettopp genererte? Ta utgangspunkt i koden for å beregne sannsynligheten til teksten vi genererte i 1.2. Spørsmål 9: Hva ville du ha endret i koden for å trene en bigramsmodell? Følg stegene over og tren din egen bigramsmodell. 2 Språkmodeller I Tabell 1 finner du en formel for en språkmodell (en såkalt bigrammodell) og et lite tekstkorpus. Bruk bigrammodellen og tekstkorpuset til å beregne sannsynligheten for setningen <s> Katherine spiller piano <\s>. Vis hvilke sannsynligheter du trenger og hvordan disse beregnes fra korpuset.

Formel: P (w 1... w k ) = k P (w i w i 1 ) i=1 Tekskorpus: <s> Petra spiller piano <\s> <s> Katherine spiller ikke piano <\s> <s> Ludovico spiller piano <\s> Table 1: Formel og tekstkorpus. 3 Flertydighet I denne oppgaven skal vi se litt nærmere på flertydigheten i språket. Vi skal bruke Python for å analysere Brown-korpuset, og vi skal fokusere på antall tildelte ordklasser til hvert ord som tegn på at et ord er flertydig. 1. Hva mener vi når vi sier at det finnes flertydighet i språket? Gi et eksempel for norsk, og et for engelsk. 2. Her skal vi bruke ordklassetaggede data fra nyhetsdelen i Brown-korpuset. Opprett en variabel brown news som en en liste av par (ord, tagg). 3. Hvor mange ord er flertydige i Brown-korpuset? Det vil si, hvor mange ord forekommer med mer enn én ordklassetagg? Hint: Her skal du benytte deg av en ordbok (dictionary) tags som for hvert ord i Brown-korpuset inneholder alle mulige ordklasser den forekommer med (disse skal være representert som en liste). 4. Hvilket ord har flest tagger, og hvor mange distinkte tagger finner du? Her kan du bruke tags som du har laget i forrige spørsmål, sammen med sorted() metoden. Hint: Når du skal bruke sorted() metoden her, sørg for at du sjekker antall elementer i listen av verdier (med tanke på values i din dictionary tags), heller enn verdiene i seg selv. 5. Skriv en funksjon freqs(w) som tar et ord som argument og skriver ut hvor ofte ordet forekommer med hver av taggene. For eksempel forekommer run 20 ganger med NN, 11 ganger med VB, og 4 ganger med VBN. 6. Ved hjelp av funksjonen fra punkt 5, finn frekvenslisten for det mest flertydige ordet i Brown. Hva observerer du? I deloppgavene 3 og 4 er det viktig at du passer på at for hvert ord telles hver distinkte tagg nøyaktig én gang; det vil si at for et ord med to forekomster med NP og tre med NN har vi listen ["NP", "NN"] og ikke ["NP", "NN", "NN", "NN", "NP"]. Merk at oppgavene her skal løses uten bruk av de NLTKs funksjonalitet for frekvens nltk.freqdist og nltk.conditionalfreqdist.