NLTK Context Free Grammar Genaration

Estoy trabajando en un analizador no inglés con caracteres Unicode. Para eso, decidí usar NLTK.

Pero requiere una gramática libre de contexto predefinida como se muestra a continuación:

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" 

En mi aplicación, se supone que debo minimizar la encoding difícil con el uso de una gramática basada en reglas. Por ejemplo, puedo asumir cualquier palabra que termine con -ed o -ing como un verbo. Así que debería funcionar para cualquier contexto dado.

¿Cómo puedo alimentar tales reglas de gramática a NLTK? ¿O generarlos dinámicamente usando la máquina de estados finitos?

¿Quizás estás buscando CFG.fromstring() (antes parse_cfg() )?

Del Capítulo 7 del libro NLTK (actualizado a NLTK 3.0):

 > grammar = nltk.CFG.fromstring(""" 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.parse(sent): print p (S (NP Mary) (VP (V saw) (NP Bob))) 

Si está creando un analizador, debe agregar un paso de etiquetado de posición antes del análisis real; no hay manera de determinar con éxito la etiqueta POS de una palabra fuera de contexto. Por ejemplo, ‘cerrado’ puede ser un adjetivo o un verbo; un etiquetador de POS encontrará la etiqueta correcta para usted en el contexto de la palabra. Luego, puede usar la salida del etiquetador de POS para crear su CFG.

Puede utilizar uno de los muchos etiquetadores POS existentes. En NLTK, simplemente puedes hacer algo como:

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

La salida será:

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

que puede utilizar para crear una cadena de gramática y alimentarla a nltk.parse_cfg() .

Puede usar NLTK RegexTagger que tiene la capacidad de expresión regular de decidir token. Esto es exactamente lo que necesitas en tu caso. Como el token que termina con ‘ing’ se marcará como gerundios y el token que termina con ‘ed’ se marcará con el verbo pasado. Vea el ejemplo a continuación.

 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 ] 

Tenga en cuenta que estos se procesan en orden y se aplica el primero que coincida. Ahora podemos configurar un etiquetador y usarlo para etiquetar una oración. Después de este paso, es correcto aproximadamente una quinta parte del tiempo.

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

puede usar Combining Taggers para usar colectivamente múltiples taggers en una secuencia.

No puedes escribir este tipo de reglas en nltk ahora sin ningún esfuerzo, pero puedes hacer algunos trucos.

Por ejemplo, transcriba su oración en algún tipo de tags informativas de palabras y escriba sus reglas gtwigticales en consecuencia.

Por ejemplo (usando la etiqueta POS como etiqueta):

 Dogs eat bones. 

se convierte en:

 NN V NN. 

Y el ejemplo de las reglas de la gramática terminal:

 V -> 'V' 

Si eso no es suficiente, debería echar un vistazo para una implementación de formalismo más flexible.