INF2820 Datalingvistikk V2012 Jan Tore Lønning
KONTEKSTFRIE GRAMMATIKKER OG PARSING 23. februar 2012 2
I dag Kontekstfrie grammatikker, avledninger og trær (delvis repetisjon) Parsing: ovenifra og ned (top-down) Parsing: nedenifra og opp (bottom-up) 23. februar 2012 3
Context-Free Grammars Det mest sentrale verktøyet i datalingvistikk 2/23/2012 Speech and Language Processing - Jurafsky and Martin 4
Eksempel: grammar1 23. februar 2012 5
Avledning α β, leses: β kan direkte avledes fra α dersom: α har formen γ C δ for en ikke-terminal C det er en regel på formen C ψ og β = γ ψ δ α 1 * α m, leses: α m kan avledes fra α 1 dersom: det fins en sekvens α 1, α 2,, α m der m>1, og α i α i+1 En kontekstfri grammatikk G generer språket L(G) = { w A* S * w} 23. februar 2012 6
Trær En CFG G, generer et tre t hviss Toppen av t er merket med S Bladene er merket med terminaler Hvert lokalt tre er tillatt av en produksjonsregel T(G) for mengde av trær generert av G Utkomme ( yield ) av treet t er symbolene på bladene i riktig rekkefølge Forkortelse: hviss for hvis og bare hvis En streng w er avledbar fra G hviss w er utkomme til et tre i T(G). 23. februar 2012 7
Høyre- og venstreavledninger Til hvert tre svarer det mange avledninger. For kontekstfrie grammatikker er forskjellene mellom avledninger som svarer til samme tre uinteressante. En avledning er en venstreavledning ( leftmost derivation ) hvis vi alltid ekspanderer ikke-terminalen lengst til venstre. Høyreavledning defineres tilsvarende. Til ethvert tre generert av grammatikken svarer det nøyaktig en venstreavledning og nøyaktig en høyreavledning. 23. februar 2012 8
Eksempel: VF og HF Venstreavledning: S NP VP Det N VP the N VP the dog VP the dog V NP PP the dog saw NP PP the dog saw Det N PP the dog saw a N PP the dog saw a man PP the dog saw a man P NP the dog saw a man in NP the dog saw a man in Det N the dog saw a man in the N the dog saw a man in the park Høyreavledning: S NP VP NP V NP PP NP V NP P NP NP V NP P Det N NP V NP P Det park NP V NP P the park NP V NP in the park NP V Det N in the park NP V Det man in the park NP V a man in the park NP saw a man in the park Det N saw a man in the park Det man saw a man in the park the dog saw a man in the park 23. februar 2012 10
I dag Kontekstfrie grammatikker, avledninger og trær (delvis repetisjon) Parsing: ovenifra og ned (top-down) Parsing: nedenifra og opp (bottom-up) 23. februar 2012 11
Parsing Gitt en grammatikk G og streng s Spm1: Er s L(G) Spørsmål om anerkjennelse ( recognition ) Spm2: Vi er interessert i (frase)strukturen til s Hvorfor er s L(G)? Finn alle trær i T(G) som har s som utkomme ( yield ) Ekvivalent: Finn alle høyreavledninger av s. Finn alle venstreavledninger av s. Parsing 23. februar 2012 12
Recursive descent parser Lager en venstreavledning Bygger et tre: Fra toppen ( top-down ) Fra venstre mot høyre Tilstrekkelig å bare se på venstreavledninger fordi de svarer til trær Streber mot tidligst mulig å sjekke mot input-data 23. februar 2012 13
Datastruktur Venstreavledning S NP VP Det N VP the N VP the dog VP the dog V NP PP the dog saw NP PP the dog saw Det N PP the dog saw a N PP the dog saw a man PP the dog saw a man P NP the dog saw a man in NP the dog saw a man in Det N the dog saw a man in the N the dog saw a man in the park Datastruktur S the dog saw a man in the park NP VP the dog saw a man in the park Det N VP the dog saw a man in the park N VP dog saw a man in the park VP saw a man in the park V NP PP saw a man in the park NP PP a man in the park Det N PP a man in the park N PP man in the park PP in the park P NP in the park NP the park Det N the park N park # # 23. februar 2012 14
Algoritme ikke-deterministisk Words, Cats: strenger (Words resten av input, Cats resten av avledningen) Words:= inputstreng Cats:= list( S ) Løkke: Hvis Words=Cats=ε: stopp med suksess! Hvis first(words)=first(cats): Words:=rest(Words), Cats:=rest(Cats) Hvis first(cats) er en ikke-terminal B, velg en regel B β, og la Cats:= β + rest(cats) 23. februar 2012 15
Kommentarer Eksempel på anerkjenning For å få parser bør vi i tillegg returnere et tre Et trinn er ikke-deterministisk: Velg en regel Dette gir et søkerom å holde orden på 23. februar 2012 16
Søkerom RD: Venstre først = prøver reglene i fast rekkefølge Dybde-først 23. februar 2012 17
def RDRecognize(grammar, words): top = grammar.start() return match(grammar, [top], words) def match(grammar, cats, words): if len(cats) == 0: return len(words) == 0 else: for p in grammar.productions(): if p.lhs() == cats[0]: if p.is_lexical(): if len(words)>0 and words[0] == p.rhs()[0]: if match(grammar, cats[1:], words[1:]): return True else: rhs = p.rhs() newcats = list(rhs) + cats[1:] if match(grammar, newcats, words): return True return False 23. februar 2012 18
Hvordan representere trær i Python En mulig enkel representasjon (blant flere): En node som ikke er et blad som et par (X, Y) der: X er moras kategori Y er listen av døtre, av type list: Hvert element i Y er selv en node Y kan være tom En bladnode er en terminal, av type string Et tre er representert som en node. (S, [(NP, [(Det, ['the']), (N, ['dog'])]), (VP, [(V, ['saw']), (NP, [(Det, ['a']), (N, ['man'])]), (PP, [(P, ['in']), (NP, [(Det, ['the']), (N, ['park'])] )])])]) 23. februar 2012 19
def RDParse(grammar, words, trace=0): top = grammar.start() init_tree = (top, []) parses = match(grammar, [init_tree], words, init_tree) def match(grammar, nodes, words, tree): """Try all possible ways for matching the *cats* and remaining *words*. Complete the *tree*. Print the successful trees for the whole sentence. Return the number of successful parses for this branch.""" if len(nodes) == 0: if len(words) == 0: skriv_tre(tree) print " " else: 23. februar 2012 20
def match(grammar, nodes, words, tree): if len(nodes) == 0: if len(words) == 0: skriv_tre(tree) else: node = nodes[0] for p in grammar.productions(): cat = node[0] if p.lhs() == cat: if p.is_lexical(): if len(words)>0 and words[0] == p.rhs()[0]: node[1].append(words[0]) match(grammar, nodes[1:], words[1:], tree) node[1].pop() else: rhs = p.rhs() daughters = [(cat,[]) for cat in rhs] node[1][0:len(daughters)]=daughters newnodes = daughters+nodes[1:] match(grammar, newnodes, words, tree) for i in range(len(node[1])): node[1].pop() 24. februar 2012 21
Problemer for RD-parsing 1. Venstrerekursjon: Hvordan takler parseren N AP N N N PP? 2. Dobbeltarbeid: Som en del av en overordnet gal analyse kan den finne riktige deler, men disse blir glemt 3. Prøving og feiling som er litt blind 23. februar 2012 22
I dag Kontekstfrie grammatikker, avledninger og trær (delvis repetisjon) Parsing: ovenifra og ned (top-down) Parsing: nedenifra og opp (bottom-up) 23. februar 2012 23
Datastruktur Høyreavledning S NP VP NP V NP PP NP V NP P NP NP V NP P Det N NP V NP P Det park NP V NP P the park NP V NP in the park NP V Det N in the park NP V Det man in the park NP V a man in the park NP saw a man in the park Det N saw a man in the park Det man saw a man in the park the dog saw a man in the park Datastruktur S # NP VP # N V NP PP # N V NP P NP # NP V NP P Det N # NP V NP P Det park NP V NP P the park NP V NP in the park NP V Det N in the park NP V Det man in the park NP V a man in the park NP saw a man in the park Det N saw a man in the park Det dog saw a man in the park # the dog saw a man in the park 23. februar 2012 24
Bottom-up: Shift reduce parser Words, Der strenger (Words resten av input, Der det som er funnet så langt) Vanlig notasjon: Der Words Words:= inputstreng Der := ε Løkke: Hvis Words=ε og Der= S stopp med suksess! Hvis mulig, gjør en av følgende: (Shift:) Hvis Words=/=ε, La Der:=Der first(words) og Words:=rest(Words) (Reduce:) Hvis det fins α, β, B, en regel B β og Der = α β: la Der= α B 23. februar 2012 25
Algoritme ikke-deterministisk Denne kan lett utvides til parser ved at vi legger inn deltrær i Der i stedet for bare kategorier. SR-parsere har problemer med tomme høyresider To plasser for valg/ikke-determinisme: Skal vi flytte eller redusere? Hva skal vi velge når vi har flere valg for reduksjon? Den kan gjøres mer effektiv hvis vi vet at høyresidene ikke blander terminaler og ikke-terminaler: Når vi flytter, gjør vi samtidig en unær reduksjon. Svarer til regel på formen B t (Vi kan også gjøre den mer effektiv hvis grammatikken er på CNF: Bare se på de to siste symbolene i Der når vi reduserer Svarer til regel på formen A BC) 23. februar 2012 26
def recognize(grammar, stack, rest, trace): if trace > 0: print stack, rest if rest==[] and len(stack)==1 and stack[0]==grammar.start(): return True else: for p in grammar.productions(): if not p.is_lexical(): rhs = list(p.rhs()) n = len(rhs) if stack[-n:] == rhs: newstack = stack[0:-n] newstack.append(p.lhs()) if recognize(grammar, newstack, rest, trace): return True if not len(rest) == 0: word = rest[0] for p in grammar.productions(): if p.is_lexical() and rest[0]==p.rhs()[0]: newst = stack[:] newst.append(p.lhs()) if recognize(grammar, newst, rest[1:], trace): return True 23. februar 2012 27
def parse(grammar, stack, rest, trees, trace): if rest == [] and len(stack)==1 and stack[0][0]==grammar.start(): trees.append(stack[0]) else: for p in grammar.productions(): if not p.is_lexical(): rhs = list(p.rhs()) n = len(rhs) top = [node[0] for node in stack[-n:]] if top == rhs: newstack = stack[0:-n] newstack.append((p.lhs(), stack[-n:])) parse(grammar, newstack, rest, trees, trace) if not len(rest) == 0: word = rest[0] for p in grammar.productions(): if p.is_lexical() and rest[0]==p.rhs()[0]: cat = p.lhs() newstack = stack[:] newstack.append((cat, [word])) newrest = rest[1:] parse(grammar,newstack, newrest, trees, trace) return trees 23. februar 2012 28