2013-07-17 29 views
9

Pracuję nad parserem w języku innym niż angielski ze znakami Unicode. W tym celu postanowiłem użyć NLTK.NLTK Kontekst Darmowe generowanie gramatyki

Ale to wymaga predefiniowanego bezkontekstowych gramatyki jak poniżej:

S -> NP VP 
    VP -> V NP | V NP PP 
    PP -> P NP 
    V -> "saw" | "ate" | "walked" 
    NP -> "John" | "Mary" | "Bob" | Det N | Det N PP 
    Det -> "a" | "an" | "the" | "my" 
    N -> "man" | "dog" | "cat" | "telescope" | "park" 
    P -> "in" | "on" | "by" | "with" 

W moim app, mam podobno zminimalizować ciężko kodowania z wykorzystaniem gramatyki z reguły oparte. Na przykład, mogę ponoszą żadnej słowo kończąc -ed lub -ing jako czasownik. Powinno działać w każdym kontekście.

Jak mogę przekazać takie reguły gramatyczne do NLTK? Lub generować je dynamicznie za pomocą Finite State Machine?

+1

Możesz przeczytać [tę odpowiedź] (http://stackoverflow.com/questions/14096237/can-someone-give-a-imple- but-non-toy-example-of-a-context- sensitiveitive -grammar/14099421 # 14099421), ponieważ piszesz CFG. –

+0

Dzięki. Patrzyłem, ale nie mogłem tego zrozumieć. Czy istnieje sposób, w jaki można karmić zmiennych Pythona do CFG? – ChamingaD

+0

Jeśli chcesz automatycznie nauczyć się zasad CFG, możesz spróbować wdrożyć tę www.aclweb.org/anthology/O06-1004 =) – alvas

Odpowiedz

2

Może szukasz parse_cfg()?

Od Chapter 7 książki NLTK:

> grammar = nltk.parse_cfg(""" 
S -> NP VP 
VP -> V NP | V NP PP 
V -> "saw" | "ate" 
NP -> "John" | "Mary" | "Bob" | Det N | Det N PP 
Det -> "a" | "an" | "the" | "my" 
N -> "dog" | "cat" | "cookie" | "park" 
PP -> P NP 
P -> "in" | "on" | "by" | "with" 
""") 

> sent = "Mary saw Bob".split() 
> rd_parser = nltk.RecursiveDescentParser(grammar) 
> for p in rd_parser.nbest_parse(sent): 
     print p 
(S (NP Mary) (VP (V saw) (NP Bob))) 
+0

Dzięki. Ale nadal trudno zakodować te czasowniki i rzeczowniki? Czy mimo to przekazujesz wartość ciągu do CFG? jak V = zmienna_a – ChamingaD

+0

Jestem pewna, że ​​można łączyć łańcuchy, a następnie przekazywać je! http://stackoverflow.com/questions/12169839/ – arturomp

+0

faktycznie, z tego, co rozumiem w twoim oryginalnym pytaniu, inną rzeczą do wypróbowania (nie do końca pewną, czy to możliwe) jest częściowe oznaczanie POS tylko na słowach kończących się na - lub -ed i oznaczyć je jako V, więc nie musisz martwić się regułą V na karcie CFG. – arturomp

7

Jeśli tworzysz parser, następnie masz dodać etap POS-tagging przed faktycznym parsowania - nie ma sposobu, aby skutecznie określić znacznik POS słowa poza kontekstem. Na przykład "zamknięty" może być przymiotnikiem lub czasownikiem; POS-tagger znajdzie odpowiedni tag dla ciebie z kontekstu słowa. Następnie możesz użyć danych wyjściowych tagera POS, aby utworzyć CFG.

Można użyć jednego z wielu istniejących POS taggers. W NLTK, można po prostu zrobić coś takiego:

import nltk 
input_sentence = "Dogs chase cats" 
text = nltk.word_tokenize(input_sentence) 
list_of_tokens = nltk.pos_tag(text) 
print list_of_tokens 

Wyjście będą:

[('Dogs', 'NN'), ('chase', 'VB'), ('cats', 'NN')] 

których można użyć, aby utworzyć ciąg gramatyki i karmić go nltk.parse_cfg().

+0

Dzięki. Czy to działa na parser inny niż angielski? – ChamingaD

+0

Nie, ale NLTK pozwala trenować własnego taggera w bardzo prosty sposób. Jednakże, aby to zrobić, będziesz potrzebował jakiegoś otagowanego korpusu twojego języka do szkolenia modelu statystycznego. Czy masz dostęp do takiego zasobu? W jakim języku pracujesz? – dkar

+0

Potrzebuję metody generowania gramatyki opartej na regułach. Na przykład wyrazy kończące się na -ed lub -ing jako czasownik (w mojej aplikacji użyję znaku Unicode). Czy jest tak w przypadku NLTK? – ChamingaD

0

Nie możesz pisać tego rodzaju zasad w NLTK teraz bez żadnego wysiłku, ale można zrobić kilka sztuczek.

Na przykład rozpisać swoje zdanie w jakiejś wytwórni słowo-informacyjny i napisać reguły gramatyczne odpowiednio.

Na przykład (przy użyciu znacznika POS jako etykiecie):

Dogs eat bones. 

staje:

NN V NN. 

i gramatyki Zasady terminalowe przykład:

V -> 'V' 

Jeśli to nie wystarczy, należy wziąć poszukiwanie bardziej elastycznego wdrożenia formalizmu.

1

Można użyć NLTK RegexTagger, które mają zdolność wyrażania regularnego tokena. To jest dokładnie to, czego potrzebujesz w swoim przypadku. Jako że token kończący się na "ing" będzie oznaczony jako gerunds, a token kończący się na "ed" zostanie oznaczony za pomocą czasownika przeszłego. zobacz przykład poniżej.

patterns = [ 
    (r'.*ing$', 'VBG'), # gerunds 
    (r'.*ed$', 'VBD'), # simple past 
    (r'.*es$', 'VBZ'), # 3rd singular present 
    (r'.*ould$', 'MD'), # modals 
    (r'.*\'s$', 'NN$'), # possessive nouns 
    (r'.*s$', 'NNS') # plural nouns 
] 

Należy zauważyć, że są one przetwarzane w kolejności i stosowana jest pierwsza dopasowana. Teraz możemy ustawić taggera i użyć go do oznaczenia zdania. Po tym kroku poprawne jest po 1/5 czasu.

regexp_tagger = nltk.RegexpTagger(patterns) 
regexp_tagger.tag(your_sent) 

można użyć Łączenie Taggers za korzystanie zbiorowo wielokrotnego tagger w sekwencji.