2015-06-14 13 views
5

Mam dwie listy i chcę sprawdzić podobieństwo pomiędzy każdymi dwoma słowami w liście i dowiedzieć się, maksymalna similarity.Here jest mój kod,Sprawdź podobieństwo między dwoma słowami z NLTK Pythona

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)) 

Ale spowoduje to błąd:

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

Proszę mi pomóc to naprawić.
Dziękując

+0

FWIW oto link do dokumentu na '.synsets': http://www.nltk.org/api/nltk.corpus.reader.html#nltk.corpus.reader.wordnet.WordNetCorpusReader.synsets – abathur

+0

spójrz na https://github.com/alvations/pywsd/blob/master/pywsd/similarity.py#L76 – alvas

Odpowiedz

6

Spróbuj sprawdzić, czy te listy są puste przed użyciem następnie:

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 Czy to działa w ten sposób? – omerbp

+0

Jestem pewien, że linia 'if len ...' będzie błędem składni. Potrafi po prostu przetestować 'if len (blah1) i len (blah2):' ponieważ on po prostu musi wiedzieć, że nie są puste. Jeśli pusty powrót z .synsets jest rzadkością, inni prawdopodobnie zasugerowaliby po prostu przechwycenie IndexError. – abathur

+0

@abathur Dzięki, poprawiłem to. Odnośnie bloków catch - zgadzam się, ale myślę, że słowo "bla" bez synonimów na drugiej liście jest bardzo powszechne, dlatego użyłem go, jeśli blok – omerbp

9

dostajesz błąd, jeśli lista synset jest pusta, i postarać się o element w (non -istniejący) indeks zero. Ale dlaczego tylko sprawdzać zero'th elementu? Jeśli chcesz sprawdzić wszystko, wypróbuj wszystkie pary elementów w zwróconych zestawach. Można użyć itertools.product() aby zapisać się na dwie pętle:

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)) 

To jest nieefektywne, ponieważ te same synsets są spojrzał znowu i znowu, ale jest najbliżej logiki kodu. Jeśli masz wystarczająco dużo danych, aby przyspieszać, możesz przyspieszyć, zbierając zestawy synchronizacyjne wszystkich słów w jednostkach list1 i list2i pobierając produkt z zestawów synchronizacyjnych.

>>> 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

Drugi fragment kodu jest niesamowity! Czy możesz mi powiedzieć, jak porównać synsety pierwszej listy z tymi samymi słowami drugiej listy, bez zestawów? Próbowałem zmodyfikować allsyns2, ale poczułem, że jestem całkiem nowym pytonem i przepraszam, że ta jedna linia kodu z dwiema pętlami jest dla mnie kłopotliwa! – Hussein

+1

Obawiam się, że nie mogę powiedzieć, co masz na myśli. Proszę rozwinąć to w odpowiednie pytanie, w tym przykładowe dane wejściowe i pożądany wynik (i oczywiście dowolny kod, którym można zarządzać). – alexis

+0

Chodziło mi o to, że jedna z dwóch list jest ustalona i znana, jak na przykład: list1 = ["word.n.01", "word2.v.01"]. Utknąłem, ponieważ nie wiedziałem, że istnieją dwie funkcje: "wordnet.synsets (word)" i "wordnet.synset (word)". Usunąłem "s" w ten sposób: set (wordnet.synset (słowo) dla słowa na liście1) i w końcu zadziałało – Hussein

Powiązane problemy