calculate path similarity score and list comprehension questions

1k views Asked by At

I have two lists of synsets generated from wordnet.synsets():

import numpy as np
import nltk
from nltk.corpus import wordnet as wn
import pandas as pd

#convert tag to the one used by wordnet
def convert_tag(tag):
    tag_dict = {'N': 'n', 'J': 'a', 'R': 'r', 'V': 'v'}
    try:
        return tag_dict[tag[0]]
    except KeyError:
        return None

#define a function to find synset reference
def doc_to_synsets(doc):
    token = nltk.word_tokenize(doc)
    tag = nltk.pos_tag(token)
    wordnet_tag = convert_tag(tag)
    syns = [wn.synsets(token, wordnet_tag) for token in nltk.word_tokenize(doc)]
    syns_list = [token[0] for token in syns if token]
    
    return syns_list

#convert two example text documents
doc1 = 'This is a test function.'
doc2 = 'Use this function to check if the code in doc_to_synsets is correct!'

s1 = doc_to_synsets(doc1)
s2 = doc_to_synsets(doc2)

I am trying to write a function to find the synset in s2 with the largest 'path similarity' score for each synset in s1. Hence, for s1, which contains 4 unique synsets, the function should return 4 path similarity scores, from which I will convert into a pandas Series object for ease of computation.

I have been working on this following code so far

def similarity_score(s1, s2):
    list = []
    for word1 in s1:
        best = max(wn.path_similarity(word1, word2) for word2 in s2)
        list.append(best)
        
    return list

However, it only return an empty list without any values in it.

[]

Would anyone care to look at what's wrong with my for loop and perhaps enlighten me on this subject?

Thank you.

1

There are 1 answers

5
Solaxun On

I removed the "Sysnet" class references since I don't have whatever that class is, and it doesn't matter for scoring purposes. The score function is abstracted out so you can define it however you like. I took a stab at a very simplistic rule. It compares each position, demarcated by the . separators, to see if they are equal. If they are, the score is incremented. For example, in s1, be.v.01 compared to a made up be.f.02 would have a score of 1, because on the prefix matches. If instead we compared to be.v.02, we would have a score of 2, etc.

s1 = [('be.v.01'),
('angstrom.n.01'),
('function.n.01'),
('trial.n.02')]

s2 = [('use.n.01'),
('function.n.01'),
('see.n.01'),
('code.n.01'),
('inch.n.01'),
('be.v.01'),
('correct.v.01')]

def score(s1,s2):
    score = 0
    for x,y in zip(s1.split('.'),s2.split('.')): 
        if x == y: 
            score += 1 
    return score

closest = [] # list of [target,best_match]

for sysnet1 in s1:
    max_score = 0
    best = None
    for sysnet2 in s2:
        cur_score = score(sysnet1,sysnet2)
        if cur_score > max_score:
            max_score = cur_score
            best = sysnet2
    closest.append([sysnet1,best])


print(closest)