2012-06-12 16 views
8

Estoy tratando de crear un identificador de sinónimo general para las palabras en una oración que son significativas (es decir, no "a" o "el"), y estoy usando el lenguaje natural toolkit (nltk) en python para él. El problema que estoy teniendo es que el buscador de sinónimos en nltk requiere un argumento de parte del discurso para poder vincularse a sus sinónimos. Mi intento de solución para esto fue utilizar el etiquetador de parte del habla simplificado presente en nltk, y luego reducir la primera letra para pasar este argumento al buscador de sinónimos, sin embargo, esto no está funcionando.Sinónimo general y parte del procesamiento de voz usando nltk

def synonyms(Sentence): 
    Keywords = [] 
    Equivalence = WordNetLemmatizer() 
    Stemmer = stem.SnowballStemmer('english') 
    for word in Sentence: 
     word = Equivalence.lemmatize(word) 
    words = nltk.word_tokenize(Sentence.lower()) 
    text = nltk.Text(words) 
    tags = nltk.pos_tag(text) 
    simplified_tags = [(word, simplify_wsj_tag(tag)) for word, tag in tags] 
    for tag in simplified_tags: 
     print tag 
     grammar_letter = tag[1][0].lower() 
     if grammar_letter != 'd': 
      Call = tag[0].strip() + "." + grammar_letter.strip() + ".01" 
      print Call 
      Word_Set = wordnet.synset(Call) 
      paths = Word_Set.lemma_names 
      for path in paths: 
       Keywords.append(Stemmer.stem(path)) 
    return Keywords 

Este es el código Actualmente estoy trabajando desde, y como se puede ver que estoy primero lematización la entrada para reducir el número de partidos que tendré en el largo plazo (I piensa ejecutar esto en decenas de miles de oraciones), y en teoría estaría derivando la palabra después de esto para aumentar este efecto y reducir el número de palabras redundantes que genero, sin embargo, este método devuelve casi invariablemente errores en la forma siguiente:

Traceback (most recent call last): 
    File "C:\Python27\test.py", line 45, in <module> 
    synonyms('spray reddish attack force') 
    File "C:\Python27\test.py", line 39, in synonyms 
    Word_Set = wordnet.synset(Call) 
    File "C:\Python27\lib\site-packages\nltk\corpus\reader\wordnet.py", line 1016, in synset 
    raise WordNetError(message % (lemma, pos)) 
WordNetError: no lemma 'reddish' with part of speech 'n' 

No tengo mucho control sobre los datos que se ejecutarán, así que simplemente limpiar mi corpus no es realmente una opción. Alguna idea sobre como resolver esto?

Investigué un poco más y tengo un liderazgo prometedor, pero todavía no estoy seguro de cómo podría implementarlo. En el caso de una palabra no encontrada o asignada incorrectamente, me gustaría utilizar una métrica de similitud (Leacock Chodorow, Wu-Palmer, etc.) para vincular la palabra con la palabra clave más cercana categorizada correctamente. Tal vez junto con una medida de distancia de edición, pero nuevamente no he podido encontrar ningún tipo de documentación sobre esto.

Respuesta

7

Aparentemente nltk permite la recuperación de todos los synsets asociados con una palabra. Por supuesto, generalmente hay varios que reflejan diferentes sentidos de la palabra. Para encontrar sinónimos funcionalmente (o si dos palabras son sinónimos) debe intentar hacer coincidir el conjunto de sinónimos más cercano posible, lo que es posible a través de cualquiera de las métricas de similitud mencionadas anteriormente. Construí un poco de código básico para hacer esto, como se muestra a continuación, cómo encontrar si dos palabras son sinónimos:

from nltk.corpus import wordnet 
from nltk.stem.wordnet import WordNetLemmatizer 
import itertools 


def Synonym_Checker(word1, word2): 
    """Checks if word1 and word2 and synonyms. Returns True if they are, otherwise False""" 
    equivalence = WordNetLemmatizer() 
    word1 = equivalence.lemmatize(word1) 
    word2 = equivalence.lemmatize(word2) 

    word1_synonyms = wordnet.synsets(word1) 
    word2_synonyms = wordnet.synsets(word2) 

    scores = [i.wup_similarity(j) for i, j in list(itertools.product(word1_synonyms, word2_synonyms))] 
    max_index = scores.index(max(scores)) 
    best_match = (max_index/len(word1_synonyms), max_index % len(word1_synonyms)-1) 

    word1_set = word1_synonyms[best_match[0]].lemma_names 
    word2_set = word2_synonyms[best_match[1]].lemma_names 
    match = False 
    match = [match or word in word2_set for word in word1_set][0] 

    return match 

print Synonym_Checker("tomato", "Lycopersicon_esculentum") 

que pueden tratar de aplicar progresivamente más fuerte derivada algoritmos, pero para las primeras pruebas que hice, esta el código realmente funcionó por cada palabra que pude encontrar. Si alguien tiene ideas sobre cómo mejorar este algoritmo, o tiene algo que mejorar esta respuesta de cualquier manera, me encantaría escucharlo.

+0

He intentado que este código funcione por un tiempo, y parece estar lleno de errores. Por un lado, "worndet" no es parte de NLTK, y la organización del paquete se ha movido un poco. – aendrew

+0

Disculpa, este código tiene 11 meses de vida. Sí, nltk cambió un poco, publicó una versión modificada y funcional para la nueva versión de nltk en lugar de la anterior. –

+0

También vale la pena señalar que las búsquedas en wordnet son en realidad bastante lentas y, en teoría, deberían delegarse en un subproceso. Si desea limpiar esto un poco más y hacer una mejor utilidad, hágamelo saber y puedo abrir una esencia para esto en Github y copiarlo en él. –

1

¿Puede envolver su Word_Set = wordnet.synset(Call) con un e ignorar la excepción WordNetError? Parece que el error que tienes es que algunas palabras no están categorizadas correctamente, pero esta excepción también ocurre para las palabras no reconocidas, por lo que captar la excepción me parece una buena idea.

+1

Para agregar a esto: WordNet no tiene todas las palabras posibles, o todos los posibles synset, por lo que simplemente no puede suponer que siempre devolverá los resultados. – Jacob

+0

WordNet podría no tener todas las palabras, pero la tasa de conversión de palabras a sinónimos es muy baja, incluso después de la lemmitización (menos del 50%). He incluido una prueba excepto, pero hay problemas más profundos que los límites de WordNet. Además, ninguna de las palabras que estoy buscando son inusuales o poco comunes. –

+1

¿Estás seguro de que las palabras están siendo identificadas como la parte correcta del discurso? [Rojizo] (http://www.thefreedictionary.com/reddish) es un Adj no un N, o no entiendo el mensaje de excepción? – ChipJust

Cuestiones relacionadas