You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

不同余弦相似度函数对Word2Vec向量计算结果差异及实现问题

问题分析与解决思路

首先得明确两个核心概念的差异,这是你产生困惑的根源:

  • 余弦相似度:公式为cosθ = (x·y) / (||x|| * ||y||),范围在[-1, 1]之间,值越接近1表示两个向量越相似。Gensim的model.wv.similarity()返回的就是这个值。
  • 余弦距离:通常定义为1 - 余弦相似度,范围在[0, 2]之间,值越接近0表示越相似。Scipy的scipy.spatial.distance.cosine()返回的是这个结果。

你的自定义cosine(x,y)返回1.0,按照余弦距离的定义,这意味着对应的余弦相似度是0,但Gensim算出的是0.075,说明你的实现大概率存在问题,最常见的原因有两个:

1. 未对向量做L2归一化

Gensim的wv.similarity()内部会先对两个向量做L2归一化(即把向量缩放成单位向量,||x||=1||y||=1),此时点积就等于余弦相似度。如果你的自定义函数没有做归一化,或者错误地跳过了范数计算步骤,就会得到完全偏离的结果。

比如如果你的函数直接计算1 - np.dot(x,y),当向量点积本身很小时(比如0.075),结果会接近1.0,这就和你看到的情况完全匹配。

2. 自定义函数的逻辑错误

这里给你两个和官方工具对齐的正确实现参考,你可以对比自己的代码排查问题:

正确的余弦相似度实现(和Gensim一致)

import numpy as np

def cosine_similarity(x, y):
    # 先做L2归一化,和Gensim内部逻辑对齐
    x_norm = x / np.linalg.norm(x)
    y_norm = y / np.linalg.norm(y)
    # 归一化后的点积等价于余弦相似度
    return np.dot(x_norm, y_norm)

正确的余弦距离实现(和Scipy一致)

import numpy as np

def cosine_distance(x, y):
    x_norm = x / np.linalg.norm(x)
    y_norm = y / np.linalg.norm(y)
    # 余弦距离 = 1 - 余弦相似度
    return 1 - np.dot(x_norm, y_norm)

用这两个函数测试你的xy

  • cosine_similarity(x,y)应该和model.wv.similarity('amber','best')结果一致(约0.075)
  • cosine_distance(x,y)应该返回1-0.075=0.925左右,而非1.0

你可以重点检查自己的cosine函数是否遗漏了归一化步骤,或者错误地简化了余弦计算的公式。

内容的提问来源于stack exchange,提问作者Art

火山引擎 最新活动