2011-05-07 21 views
21

Estoy tratando de crear un pequeño lenguaje similar al inglés para especificar tareas. La idea básica es dividir una declaración en verbos y sintagmas nominales a los que se deberían aplicar esos verbos. Estoy trabajando con NLTK pero no obtener los resultados que yo esperaba, por ejemplo:etiquetado personalizado con nltk

>>> nltk.pos_tag(nltk.word_tokenize("select the files and copy to harddrive'")) 
[('select', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('and', 'CC'), ('copy', 'VB'), ('to', 'TO'), ("harddrive'", 'NNP')] 
>>> nltk.pos_tag(nltk.word_tokenize("move the files to harddrive'")) 
[('move', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')] 
>>> nltk.pos_tag(nltk.word_tokenize("copy the files to harddrive'")) 
[('copy', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')] 

En cada caso se ha dado cuenta de la primera palabra (seleccionar, mover y copiar) fueron pensados ​​como verbos. Sé que puedo crear etiquetas y gramáticas personalizadas para evitar esto, pero al mismo tiempo tengo dudas de reinventar la rueda cuando muchas de estas cosas están fuera de mi alcance. En particular, preferiría una solución donde también se puedan manejar idiomas que no sean inglés.

Así que de todos modos, mi pregunta es una de: ¿Hay un mejor grabador para este tipo de gramática? ¿Hay alguna manera de ponderar un etiquetador existente para usar la forma verbal con más frecuencia que la forma del sustantivo? ¿Hay alguna manera de entrenar a un etiquetador? ¿Hay una mejor manera en total?

Respuesta

22

Una solución es crear un manual UnigramTagger que retroceda al etiquetador NLTK. Algo como esto:

>>> import nltk.tag, nltk.data 
>>> default_tagger = nltk.data.load(nltk.tag._POS_TAGGER) 
>>> model = {'select': 'VB'} 
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger) 

A continuación presentamos lo mejor

>>> tagger.tag(['select', 'the', 'files']) 
[('select', 'VB'), ('the', 'DT'), ('files', 'NNS')] 

Este mismo método puede funcionar para idiomas distintos del inglés, siempre y cuando usted tiene un etiquetador por defecto apropiado. Puede entrenar a sus propios etiquetadores usando train_tagger.py de nltk-trainer y un corpus apropiado.

19

La respuesta de Jacob es perfecta. Sin embargo, para ampliarlo, es posible que necesite algo más que unigramas.

Por ejemplo, considere las tres frases:

select the files 
use the select function on the sockets 
the select was good 

Aquí, la palabra "seleccionar" está siendo utilizado como un verbo, adjetivo y sustantivo, respectivamente. Un etiquetador de unigram no podrá modelar esto. Incluso un etiquetador de bigram no puede manejarlo, porque dos de los casos comparten la misma palabra anterior (es decir, "la"). Necesitarás un etiquetador de trigrama para manejar este caso correctamente.

import nltk.tag, nltk.data 
from nltk import word_tokenize 
default_tagger = nltk.data.load(nltk.tag._POS_TAGGER) 

def evaluate(tagger, sentences): 
    good,total = 0,0. 
    for sentence,func in sentences: 
     tags = tagger.tag(nltk.word_tokenize(sentence)) 
     print tags 
     good += func(tags) 
     total += 1 
    print 'Accuracy:',good/total 

sentences = [ 
    ('select the files', lambda tags: ('select', 'VB') in tags), 
    ('use the select function on the sockets', lambda tags: ('select', 'JJ') in tags and ('use', 'VB') in tags), 
    ('the select was good', lambda tags: ('select', 'NN') in tags), 
] 

train_sents = [ 
    [('select', 'VB'), ('the', 'DT'), ('files', 'NNS')], 
    [('use', 'VB'), ('the', 'DT'), ('select', 'JJ'), ('function', 'NN'), ('on', 'IN'), ('the', 'DT'), ('sockets', 'NNS')], 
    [('the', 'DT'), ('select', 'NN'), ('files', 'NNS')], 
] 

tagger = nltk.TrigramTagger(train_sents, backoff=default_tagger) 
evaluate(tagger, sentences) 
#model = tagger._context_to_tag 

nota, puede utilizar NLTK de NgramTagger para entrenar a un etiquetador usando un número arbitrariamente alto de n-gramas, pero por lo general usted no recibe mucho más de rendimiento después de trigramas.

+0

¿Es posible utilizar un modelo (como en respuesta Jacobs) y la sentencia de formación (como en esta respuesta)? – Sadik

3

Ver la respuesta de Jacob.

En versiones posteriores (al menos nltk 3.2) nltk.tag._POS_TAGGER no existe. Los etiquetadores por defecto suelen ser descargados en el/los grafiteros/directorio nltk_data, por ejemplo .:

>>> import nltk 
>>> nltk.download('maxent_treebank_pos_tagger') 

El uso es como sigue.

>>> import nltk.tag, nltk.data 
>>> tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle' 
>>> default_tagger = nltk.data.load(tagger_path) 
>>> model = {'select': 'VB'} 
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger) 

Ver también: How to do POS tagging using the NLTK POS tagger in Python.

0

La respuesta de Bud es correcta.También, de acuerdo con this link,

si sus paquetes nltk_data se han instalado correctamente, entonces NLTK sabe dónde están en el sistema, y ​​no es necesario pasar una ruta absoluta.

Significado, puede simplemente decir

tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle' 
default_tagger = nltk.data.load(tagger_path)