查找单词之间的余弦相似度

问题描述

是否可以找到两个单词之间的相似性?例如:

cos_lib = cosine_similarity('kamra','cameras')

这给我一个错误

ValueError: Could not convert string to float: 'kamra'

因为我还没有将单词转换成数值向量。我该怎么办?我试过了,但是也行不通:

('kamra').toarray()

我的目的是检查字典的两个值(列表)的相似性,并返回相似性最高的键。有可能吗?

features = {"CAMERA": ['camera','kamras'],"BATTERY": ['batterie','battery']}

我也尝试过这样做,但对结果不满意:

print(damerau.distance('dual camera','cameras'))
print(damerau.distance('kamra','battery'))

,因为结果是6和5。但是前两个字符串之间的相似度更大,因此距离应该更短。这就是我想要达到的目标。

解决方法

余弦距离总是定义在两个相同长度的实向量之间。

对于单词/句子/字符串,距离有两种:

最小编辑距离::这是使两个单词具有相同字符所需的更改次数。这些词对于定义MED不需要有任何含义。例如,字符串abcdabed具有MED = 1。但是它们在语言上没有真正的意义。

语义距离::这是衡量单词相隔多远的意思。因此,您需要在此处创建词汇表,并在其上方构建模型。在这里,单词被转换成代表其相对含义的数值向量。例如,代表treewood的向量比kingqueen的向量更近。可以使用Word2Vec这样的通用模型或BERTGPT-2这样的高端神经网络来获得单词的矢量表示。向量表示之间的余弦距离是一种语义距离。语义距离的另一种类型是欧氏距离。

注意:在语义表示的情况下,与词汇表中的任何单词都不匹配的所有单词(例如kamraabcxyz)将全部归为一种含义,表示{unknown word}。

对于您的特定用例,我建议运行MED以从词汇表中获取最可能出现的单词,然后是某种形式的语义距离。您可以为前者尝试一些自动更正API。

,

我建议使用Gensim中的预训练模型。您可以下载经过预训练的模型,然后获取两个向量之间的余弦相似度。

import gensim.downloader as api
# overview of all models in gensim: https://github.com/RaRe-Technologies/gensim-data
model_glove = api.load("glove-wiki-gigaword-100")

model_glove.relative_cosine_similarity("politics","vote")
# output: 0.07345439049627836
model_glove.relative_cosine_similarity("film","camera")
# output: 0.06281138757741007
model_glove.relative_cosine_similarity("economy","fart")
# output: -0.01170896437873441

尽管如此,预训练模型很难识别拼写错误,因为它们可能不在训练数据中。找出这些是与余弦相似度分开的任务。

model_glove.relative_cosine_similarity("kamra","cameras")
# output: -0.040658474068872255

但是,如果您有多个单词,并且想要从列表中选择最相似的单词,以下功能可能会很有用:

model_glove.most_similar_to_given("camera",["kamra","movie","politics","umbrella","beach"])
# output: 'movie'
,

幸运的是,有一些库可以做到这一点,例如word2vec。您需要在某些数据集上对其进行训练,或者下载预训练的模型(针对您的特定语言或一组语言)。