词向量相似精度

2024-06-10 04:37:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图手动实现Gensim的most_similar函数,但计算查询词和其他一个词之间的相似度(避免了用所有其他词计算查询词的时间)。到目前为止,我使用

cossim = (np.dot(a, b)
                   / np.linalg.norm(a)
                   / np.linalg.norm(b))

这与ab之间的相似性结果相同。我发现这几乎完全有效,但例如,有些精度丢失了

from gensim.models.word2vec import Word2Vec
import gensim.downloader as api

model_gigaword = api.load("glove-wiki-gigaword-300")

a = 'france'
b = 'chirac'

cossim1 = model_gigaword.most_similar(a)
import numpy as np
cossim2 = (np.dot(model_gigaword[a], model_gigaword[b])
                   / np.linalg.norm(model_gigaword[a])
                   / np.linalg.norm(model_gigaword[b]))
print(cossim1)
print(cossim2)

输出:

[('french', 0.7344760894775391), ('paris', 0.6580672264099121), ('belgium', 0.620672345161438), ('spain', 0.573593258857727), ('italy', 0.5643460154533386), ('germany', 0.5567398071289062), ('prohertrib', 0.5564222931861877), ('britain', 0.5553334355354309), ('chirac', 0.5362644195556641), ('switzerland', 0.5320892333984375)]
0.53626436

所以最相似的函数给出了0.53626441955。。。(四舍五入为0.53626442),使用numpy计算得出0.53626436。类似地,您可以看到“巴黎”和“意大利”的值之间的差异(与“法国”相似)。这些差异表明计算没有达到完全精度(但它是在Gensim中进行的)。我如何修正它并获得单个相似性的更高精度的输出,就像它来自大多数相似性一样

TL/DR-我想使用函数('france','chirac')得到0.5362644195556641,而不是0.53626436

知道发生了什么吗


更新:我应该澄清一下,我想知道和复制最相似的是如何进行计算的,但只针对一对(a,b)。这是我的首要任务,而不是找出如何提高上述cossim计算的精度。我只是假设两者是等价的


Tags: 函数importnormmostmodelnp精度相似性
2条回答

要提高精度,您可以尝试以下方法:

a = np.array(model_gigaword[a]).astype('float128')
b = np.array(model_gigaword[b]).astype('float128')
cossim = (np.dot(a, b)
                   / np.linalg.norm(a)
                   / np.linalg.norm(b))

向量可能使用精度较低的浮动,因此在计算中存在精度损失

但是,我得到的结果与model_gigaword.most_similar为您提供的结果有些不同:

model_gigaword.similarity: 0.5362644
float64:  0.5362644263010196
float128: 0.53626442630101950744

您可能需要检查您的机器上以及您的Python和gensim版本上得到了什么

因为浮点数(如这些向量模型中的np.float32类型的值)是使用不精确的二进制近似表示的,所以您正在处理或显示的数字都不是您认为的精确的十进制数

您看到的0.53626436数字并不完全是这个数字,但是一些二进制浮点数非常接近这个数字。类似地,您看到的0.5362644195556641数字并不完全是这个数字,而是其他一些二进制浮点数,非常接近这个数字

此外,这些微小的不精确性可能意味着,在理想情况下,数学表达式应该彼此给出相同的结果,而不管求值顺序如何,相反,对于不同的求值顺序,给出的结果略有不同。例如,我们知道在数学上,a * (b + c)总是等于ab + ac。然而,如果ab,&c是精度有限的浮点数,执行加法然后乘法,与执行两次乘法然后一次加法的结果相比,可能会有所不同,因为中间值的近似值会略有不同

但是:对于使用这些数字的几乎所有领域来说,这一微小的噪音应该不会有任何区别。正确的策略是忽略它,并以极低的显著性数字编写对这种小“抖动”鲁棒的代码-尤其是当打印比较结果时

因此,实际上,您应该只打印/比较这些数字的重要程度,即它们可靠地一致,比如小数点后的4位数字:

0.536264360.5362644195556641

(事实上,您的输出已经使它看起来像是您更改了numpypython中显示精度的默认级别,因为most_simlar()的结果在小数点后以这16位数字显示不是典型的。)

如果您真的,真的想,作为一种探索,精确地匹配most_similar()结果,您可以查看它的源代码。然后,使用完全相同的库例程,以完全相同的顺序对输入执行完全相同的步骤

(以下是当前gensim-4.0.0beta预发行版中most_similar()的源代码:https://github.com/RaRe-Technologies/gensim/blob/4.0.0beta/gensim/models/keyedvectors.py#L690

但是:坚持这样精确的通信通常是不明智的;考虑到浮点数学固有的不精确性,创建更脆弱的代码

另请参见:another answer covering some similar issues,它还指出了更改默认显示精度的方法

相关问题 更多 >