Я предлагаю двухэтапный подход:
Сначала найдите синонимы, сравнив вложения слов (только не стоп-слова). Это должно удалить похожие письменные слова, которые означают что-то еще, например, gasoline
и gaseous
.
Затем проверьте, имеют ли синонимы общий смысл. По сути if "gas" is in "gasolin"
и наоборот. Этого будет достаточно, потому что вы сравниваете только свои синонимы.
import spacy
import itertools
from nltk.stem.porter import *
threshold = 0.6
#compare the stems of the synonyms
stemmer = PorterStemmer()
def compare_stems(a, b):
if stemmer.stem(a) in stemmer.stem(b):
return True
if stemmer.stem(b) in stemmer.stem(a):
return True
return False
candidate_synonyms = {}
#add a candidate to the candidate dictionary of sets
def add_to_synonym_dict(a,b):
if a not in candidate_synonyms:
if b not in candidate_synonyms:
candidate_synonyms[a] = {a, b}
return
a, b = b,a
candidate_synonyms[a].add(b)
nlp = spacy.load('en_core_web_lg')
text = u'The price of gasoline has risen. "Gas" is a colloquial form of the word gasoline in North American English. Conversely in BE the term would be petrol. A gaseous state has nothing to do with oil.'
words = nlp(text)
#compare every word with every other word, if they are similar
for a, b in itertools.combinations(words, 2):
#check if one of the word pairs are stopwords or punctuation
if a.is_stop or b.is_stop or a.is_punct or b.is_punct:
continue
if a.similarity(b) > threshold:
if compare_stems(a.text.lower(), b.text.lower()):
add_to_synonym_dict(a.text.lower(), b.text.lower())
print(candidate_synonyms)
#output: {'gasoline': {'gas', 'gasoline'}}
Затем вы можете подсчитывать кандидатов-синонимов по их появлению в тексте.
Примечание: Я выбрал порог для синонимов с 0,6 случайно. Вы бы, вероятно, проверили, какой порог соответствует вашей задаче Кроме того, мой код - простой и грязный пример, это можно сделать намного чище. `