2016-07-01 1 views
0

J'essaie de calculer les chemins les plus courts entre toutes les paires de noms d'un groupe. J'ai beaucoup de tels groupes de noms avec différentes tailles de groupe. Le plus grand groupe contient environ 250 noms. L'entrée est un fichier txt avec des noms, chacun sur une nouvelle ligne. La sortie en tant que fichier txt doit répertorier toutes les paires de noms avec les chemins les plus courts correspondants.Comment calculer les chemins les plus courts entre toutes les paires de noms dans un groupe avec NLTK, WordNet et similarité?

Je suis nouveau à python et NLTK, et après beaucoup de recherche ici et d'autres sources, de nombreux essais et erreurs, c'est le code que je suis venu:

import nltk 
from nltk.corpus import wordnet as wn 

listSim = [] 
with open("words-input.txt", "rU") as wordList1: 
    myList1 = [line.rstrip('\n') for line in wordList1] 
    for word1 in myList1: 
     with open("words-input2.txt", "rU") as wordList2: 
      myList2 = [line.rstrip('\n') for line in wordList2] 
      for word2 in myList2: 
       wordFromList1 = wn.synsets(word1) 
       wordFromList2 = wn.synsets(word2) 
       if wordFromList1 and wordFromList2: 
        s = 1/(wordFromList1[0].path_similarity(wordFromList2[0])) 
        sym = (word1, word2, s) 
        listSim.append(sym) 

print (listSim) 
with open("words-output.txt", "w") as text_file: 
    print (listSim, file=text_file) 

(Juste à noter, je pouvais ne pas répéter avec succès le même fichier txt, j'ai donc fait un doublon, et les mots-input.txt et mots-input2.txt dans le code ci-dessus contiennent le même groupe de noms dans le même ordre.)

Le problème avec mon code est qu'il ne calcule que le plus court chemin entre les premiers synsets (première signification - n # 1) des noms. Par exemple, si le chemin le plus court semble être entre n # 3 de nom1 et n # 5 de nom2, c'est le nombre que je dois produire (ou réciproque, représentant le nombre de pas sur ce chemin).

Une aide ou un conseil pour ce faire sera grandement apprécié.

Répondre

3

Ce qui suit devrait faire pour vous, je ne fournis que les pièces pertinentes.

from itertools import product 

for word1 in myList1: 
    for word2 in myList2: 
     list1 = wn.synsets(word1) 
     list2 = wn.synsets(word2) 

     sList = [ss1.path_similarity(ss2) for ss1, ss2 in product(list1, list2)] 

     best = sorted(sList, reverse=True)[0] 
     listSim.append((word1, word2, best)) 
+0

Merci pour la réponse! J'ai eu autre problème avec « Aucun » dans sList ci-dessus, mais votre code travaillé avec la modification suivante: de l'importation de l'opérateur is_not de functools importer partielle sListFilter = filtre (partiel (is_not, None), sList) – Georgi

+0

Heureux d'avoir aidé. Vous ne savez pas pourquoi vous avez eu des problèmes avec None - si 'list1' ou' list2' sont vides, la liste des produits (et par conséquent 'sList') devient également vide, donc le problème que vous devriez obtenir est" index sur range "dans la ligne qui obtient le" meilleur ". En tous cas :) – dkar