我尝试使用余弦距离(source)计算两个单词的相似度。这是代码:
def word2vec(word):
from collections import Counter
from math import sqrt
# count the characters in word
cw = Counter(word)
# precomputes a set of the different characters
sw = set(cw)
# precomputes the "length" of the word vector
lw = sqrt(sum(c*c for c in cw.values()))
# return a tuple
return cw, sw, lw
def cosdis(v1, v2):
# which characters are common to the two words?
common = v1[1].intersection(v2[1])
# by definition of cosine distance we have
return sum(v1[0][ch]*v2[0][ch] for ch in common)/v1[2]/v2[2]
当我打电话时相似度为0.1889822365046136:
cosdis(word2vec('tahu') , word2vec('tempe'))
当尝试使用库(gensim word2vec)与相似性结果进行比较时,结果是不同的(例如,差异为0.2)。这是为什么?这就是我使用库获得相似性的方式:
from gensim.models import Word2Vec
modelword2vec = Word2Vec.load("/idwiki_word2vec_300.model")
modelword2vec.similarity('tahu' , 'tempe')
相似度是0.21785985
没有理由期望它们是相同的。关于它们内部的一切都没有相似之处。
您显示的word2vec()
函数是从其他混淆的SO答案复制而来的,通常不是人们所说的'word2vec'。它计算单词中的某些字符数–对我来说似乎没有用,但是无论如何。
cosdis()
可能类似地被混淆;也许是影响单词的真实余弦距离计算,其中每个维度都是字符数。 (请注意,任何这样的“向量”最多具有26个尺寸,每个字母一个。)但更好的方法是将cw
计数转换为实际的array
类型,如流行的[C0 ]库,然后使用余弦距离的显式且可靠的库实现。
另一方面,您的numpy
代码显示正在加载一个实际的gensim
模型,该模型可能是根据实际文本训练的。因此,它将为每个单词提供密集的,学习的语义矢量-每个单词通常具有100个或更多个维度,这与每个单词中的字符数绝对无关。
[当您向Word2Vec
询问该模型时,它将对那些完整向量执行余弦相似度计算。请注意,余弦相似度和余弦距离不是同一回事。
您基于字符的“向量”在结构/形状/内部值上与其他模型中单词的向量不同:因此,即使similarity()
实际上是余弦相似度的精确实现,您仍然不会获得匹配的值。