2015-06-14 21 views
5

Ho un due liste e voglio controllare la somiglianza tra ogni parola nella lista di secondo e scoprire la massima similarity.Here è il mio codice,Controllare la somiglianza tra due parole con NLTK con Python

from nltk.corpus import wordnet 

list1 = ['Compare', 'require'] 
list2 = ['choose', 'copy', 'define', 'duplicate', 'find', 'how', 'identify', 'label', 'list', 'listen', 'locate', 'match', 'memorise', 'name', 'observe', 'omit', 'quote', 'read', 'recall', 'recite', 'recognise', 'record', 'relate', 'remember', 'repeat', 'reproduce', 'retell', 'select', 'show', 'spell', 'state', 'tell', 'trace', 'write'] 
list = [] 

for word1 in list1: 
    for word2 in list2: 
     wordFromList1 = wordnet.synsets(word1)[0] 
     wordFromList2 = wordnet.synsets(word2)[0] 
     s = wordFromList1.wup_similarity(wordFromList2) 
     list.append(s) 

print(max(list)) 

Ma questo risulterà un errore:

wordFromList2 = wordnet.synsets(word2)[0] 
     IndexError: list index out of range 

per favore mi aiuti a risolvere questo problema.
Ringraziandovi

+0

FWIW, ecco un link al documento per '.synsets': http://www.nltk.org/api/nltk.corpus.reader.html#nltk.corpus.reader.wordnet.WordNetCorpusReader.synsets – abathur

+0

dai uno sguardo a https://github.com/alvations/pywsd/blob/master/pywsd/similarity.py#L76 – alvas

risposta

6

Prova a controllare se queste liste sono vuote prima di utilizzare poi:

from nltk.corpus import wordnet 

list1 = ['Compare', 'require'] 
list2 = ['choose', 'copy', 'define', 'duplicate', 'find', 'how', 'identify', 'label', 'list', 'listen', 'locate', 'match', 'memorise', 'name', 'observe', 'omit', 'quote', 'read', 'recall', 'recite', 'recognise', 'record', 'relate', 'remember', 'repeat', 'reproduce', 'retell', 'select', 'show', 'spell', 'state', 'tell', 'trace', 'write'] 
list = [] 

for word1 in list1: 
    for word2 in list2: 
     wordFromList1 = wordnet.synsets(word1) 
     wordFromList2 = wordnet.synsets(word2) 
     if wordFromList1 and wordFromList2: #Thanks to @alexis' note 
      s = wordFromList1[0].wup_similarity(wordFromList2[0]) 
      list.append(s) 

print(max(list)) 
+0

@Punuth Funziona in questo modo? – omerbp

+0

Abbastanza sicuro che la riga 'if len ...' sarà un errore di sintassi. Si può anche testare 'se len (blah1) e len (blah2):' dal momento che ha solo bisogno di sapere che non sono vuoti. Se un ritorno vuoto da .synsets è raro, altri probabilmente suggerirebbero semplicemente di catturare l'errore IndexError. – abathur

+0

@abathur Grazie, l'ho corretto. Per quanto riguarda i blocchi di cattura - sono d'accordo, ma penso che una parola "blah" non abbia sinonimi all'interno di una seconda lista è molto comune, quindi ho usato se il blocco – omerbp

9

Stai diventando un errore se l'elenco synset è vuota, e si tenta di ottenere l'elemento in (non -esistente) indice zero. Ma perché controllare solo l'elemento zero? Se si desidera controllare tutto, provare tutte le coppie di elementi nei synset restituiti. È possibile utilizzare itertools.product() per risparmiare due per-loop:

from itertools import product 
sims = [] 

for word1, word2 in product(list1, list2): 
    syns1 = wordnet.synsets(word1) 
    syns2 = wordnet.synsets(word2) 
    for sense1, sense2 in product(syns1, syns2): 
     d = wordnet.wup_similarity(sense1, sense2) 
     sims.append((d, syns1, syns2)) 

Questo è inefficiente perché gli stessi synsets sono guardato ancora e ancora, ma è il più vicino alla logica del codice. Se si dispone di dati sufficienti per rendere la velocità un problema, è possibile accelerarlo raccogliendo i synset per tutte le parole in list1 e list2una volta e prendendo il prodotto dei synset.

>>> allsyns1 = set(ss for word in list1 for ss in wordnet.synsets(word)) 
>>> allsyns2 = set(ss for word in list2 for ss in wordnet.synsets(word)) 
>>> best = max((wordnet.wup_similarity(s1, s2) or 0, s1, s2) for s1, s2 in 
     product(allsyns1, allsyns2)) 
>>> print(best) 
(0.9411764705882353, Synset('command.v.02'), Synset('order.v.01')) 
+0

Il secondo pezzo di codice è fantastico! Puoi dirmi come confrontare i synset della prima lista con le stesse parole della seconda lista, senza synset? Ho provato a modificare allsyns2 ma mi sono sentito, sono abbastanza nuovo per Python e mi spiace che questa riga di codice con due loop sia confusa per me! – Hussein

+1

Ho paura di non poter dire cosa intendi. Si prega di espanderlo in una domanda appropriata, incluso l'input di esempio e l'output desiderato (e qualsiasi codice che possiate gestire, ovviamente). – alexis

+0

Quello che intendevo era che uno dei due elenchi è fisso e conosciuto, come questo: list1 = ['word.n.01', 'word2.v.01']. Mi sono bloccato perché non sapevo che esistono due funzioni: "wordnet.synsets (word)" e "wordnet.synset (word)". Ho rimosso il "s" in questo modo: set (wordnet.synset (word) per word in list1) e infine ha funzionato – Hussein