如何在词/物词典中查找前 N 个相似词?
How to Find Top N Similar Words in a Dictionary of Words / Things?
我有一个 str
的列表,我想根据这些列表进行映射。这些词可以是“金属”或“圣帕特里克”。目标是针对此列表映射一个新字符串并找到前 N 个相似项目。比如我路过“St. Patrick”,我想捕获“st patrick”或者“saint patrick”。
我知道有 gensim 和 fastText,我有一种直觉,我应该追求余弦相似度(或者如果有其他建议,我会洗耳恭听)。我主要处理时间序列,而 gensim 模型训练似乎不喜欢单词列表。
下一步我应该瞄准什么?
首先,您必须决定您是对拼字相似性感兴趣还是对语义相似性感兴趣。
正字法相似度
在这种情况下,您计算两个字符串之间的距离。有various metrics for computing edit distance. Levenshtein distance is the most common: you can find various python implementations, like this.
“gold”类似于“good”,但不类似于“metal”。
语义相似度
在这种情况下,您测量两个字符串有多少具有相似的含义。
fastText 和其他词嵌入属于这种情况,即使它们也考虑了拼写方面。
“金”更像“金属”而不是“好”。
如果您的列表中的单词数量有限,您可以使用existing word embedding,在您的语言上进行预训练。基于此词嵌入,您可以计算列表中每个 word/sentence 的词向量,然后使用余弦相似度将新词的向量与列表中的向量进行比较。
import fasttext
import numpy as np
# download English pretrained model
fasttext.util.download_model('en', if_exists='ignore')
ft = fasttext.load_model('cc.en.300.bin')
def cos_sim(a, b):
"""Takes 2 vectors a, b and returns the cosine similarity according
to the definition of the dot product
(https://masongallo.github.io/machine/learning,/python/2016/07/29/cosine-similarity.html)
"""
dot_product = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
return dot_product / (norm_a * norm_b)
def compare_word(w, words_vectors):
"""
Compares new word with those in the words vectors dictionary
"""
vec=ft.get_sentence_vector(w)
return {w1:cos_sim(vec,vec1) for w1,vec1 in words_vectors.items()}
# define your word list
words_list=[ "metal", "st. patrick", "health"]
# compute words vectors and save them into a dictionary.
# since there are multiwords expressions, we use get_sentence_vector method
# instead, you can use get_word_vector method
words_vectors={w:ft.get_sentence_vector(w) for w in words_list}
# try compare_word function!
compare_word('saint patrick', words_vectors)
# output: {'metal': 0.13774191, 'st. patrick': 0.78390956, 'health': 0.10316559}
compare_word('copper', words_vectors)
# output: {'metal': 0.6028242, 'st. patrick': 0.16589196, 'health': 0.10199054}
compare_word('ireland', words_vectors)
# output: {'metal': 0.092361264, 'st. patrick': 0.3721483, 'health': 0.118174866}
compare_word('disease', words_vectors)
# output: {'metal': 0.10678574, 'st. patrick': 0.07039305, 'health': 0.4192972}
我有一个 str
的列表,我想根据这些列表进行映射。这些词可以是“金属”或“圣帕特里克”。目标是针对此列表映射一个新字符串并找到前 N 个相似项目。比如我路过“St. Patrick”,我想捕获“st patrick”或者“saint patrick”。
我知道有 gensim 和 fastText,我有一种直觉,我应该追求余弦相似度(或者如果有其他建议,我会洗耳恭听)。我主要处理时间序列,而 gensim 模型训练似乎不喜欢单词列表。
下一步我应该瞄准什么?
首先,您必须决定您是对拼字相似性感兴趣还是对语义相似性感兴趣。
正字法相似度
在这种情况下,您计算两个字符串之间的距离。有various metrics for computing edit distance. Levenshtein distance is the most common: you can find various python implementations, like this.
“gold”类似于“good”,但不类似于“metal”。
语义相似度
在这种情况下,您测量两个字符串有多少具有相似的含义。
fastText 和其他词嵌入属于这种情况,即使它们也考虑了拼写方面。
“金”更像“金属”而不是“好”。
如果您的列表中的单词数量有限,您可以使用existing word embedding,在您的语言上进行预训练。基于此词嵌入,您可以计算列表中每个 word/sentence 的词向量,然后使用余弦相似度将新词的向量与列表中的向量进行比较。
import fasttext
import numpy as np
# download English pretrained model
fasttext.util.download_model('en', if_exists='ignore')
ft = fasttext.load_model('cc.en.300.bin')
def cos_sim(a, b):
"""Takes 2 vectors a, b and returns the cosine similarity according
to the definition of the dot product
(https://masongallo.github.io/machine/learning,/python/2016/07/29/cosine-similarity.html)
"""
dot_product = np.dot(a, b)
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
return dot_product / (norm_a * norm_b)
def compare_word(w, words_vectors):
"""
Compares new word with those in the words vectors dictionary
"""
vec=ft.get_sentence_vector(w)
return {w1:cos_sim(vec,vec1) for w1,vec1 in words_vectors.items()}
# define your word list
words_list=[ "metal", "st. patrick", "health"]
# compute words vectors and save them into a dictionary.
# since there are multiwords expressions, we use get_sentence_vector method
# instead, you can use get_word_vector method
words_vectors={w:ft.get_sentence_vector(w) for w in words_list}
# try compare_word function!
compare_word('saint patrick', words_vectors)
# output: {'metal': 0.13774191, 'st. patrick': 0.78390956, 'health': 0.10316559}
compare_word('copper', words_vectors)
# output: {'metal': 0.6028242, 'st. patrick': 0.16589196, 'health': 0.10199054}
compare_word('ireland', words_vectors)
# output: {'metal': 0.092361264, 'st. patrick': 0.3721483, 'health': 0.118174866}
compare_word('disease', words_vectors)
# output: {'metal': 0.10678574, 'st. patrick': 0.07039305, 'health': 0.4192972}