2015-06-14 6 views
5

У меня есть два списка, и я хочу, чтобы проверить сходство между каждыми словами в два списка и выяснить, максимальная similarity.Here мой код,Проверьте сходство между двумя словами с NLTK с 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)) 

Но это приведет к ошибке:

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

Пожалуйста, помогите мне исправить это.
Благодаря вам

+0

FWIW вот ссылка на документ для '.synsets': http://www.nltk.org/api/nltk.corpus.reader.html#nltk.corpus.reader.wordnet.WordNetCorpusReader.synsets – abathur

+0

взгляните на https://github.com/alvations/pywsd/blob/master/pywsd/similarity.py#L76 – alvas

ответ

6

Попробуйте проверить, являются ли эти списки пусты, прежде чем использовать то:

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 Работает ли это так? – omerbp

+0

Довольно уверен, что строка 'if len ...' будет синтаксической ошибкой. Также можно просто проверить 'if len (blah1) и len (blah2):', поскольку он просто должен знать, что они не пустые. Если пустое возвращение из .synsets встречается редко, другие, вероятно, предпочтут просто поймать IndexError. – abathur

+0

@abathur Спасибо, я исправил его. Что касается блоков catch - я согласен, но я думаю, что слово 'blah', не имеющее синонимов во втором списке, очень распространено, поэтому я использовал if block – omerbp

9

Вы получаете сообщение об ошибке, если список synset пуст, и вы пытаетесь получить элемент в (не -сильный) нулевой индекс. Но зачем только проверять нулевой элемент? Если вы хотите проверить все, попробуйте все пары элементов в возвращаемых synsets. Вы можете использовать itertools.product(), чтобы сохранить себя два для петель:

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

Это неэффективно, так как одни и те же synsets смотрят снова и снова, но это ближе всего к логике кода. Если у вас достаточно данных, чтобы сделать скорость проблемой, вы можете ускорить ее, собирая synsets для всех слов в list1 и list2один раз и взяв продукт synsets.

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

Вторая часть кода является удивительной! Не могли бы вы рассказать мне, как сравнить синтаксисы первого списка с теми же словами второго списка без синтаксисов? Я попытался изменить allsyns2, но я чувствовал, что я довольно новичок в python и сожалею, что эта строка кода с двумя циклами запутывает меня! – Hussein

+1

Боюсь, я не могу сказать, что вы имеете в виду. Пожалуйста, разверните это в правильный вопрос, включая пример ввода и желаемого вывода (и любой код, который вы можете управлять, конечно). – alexis

+0

Я имел в виду, что один из двух списков фиксирован и известен, например: list1 = ['word.n.01', 'word2.v.01']. Я застрял, потому что не знал, что есть две функции: «wordnet.synsets (word)» и «wordnet.synset (word)». Я удалил 's' следующим образом: set (wordnet.synset (word) для слова в списке1), и он, наконец, работал – Hussein