You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

cosine_similarity输出全为1且维度不兼容问题排查求助

问题:计算电影标签平均Word2Vec向量余弦相似度时的异常问题

我尝试计算某部电影标签的平均Word2Vec向量与其他所有电影的平均Word2Vec向量的余弦相似度,但cosine_similarity的输出始终全为1,甚至传入相同电影向量时也是如此,同时还出现维度不兼容的错误,具体细节如下:


1. Word2Vec模型训练代码

model = gensim.models.Word2Vec(window=10, min_count=1, workers=8, vector_size=300, alpha=0.03, min_alpha=0.0007)
model.build_vocab(flatten_corpus) # flatten_corpus为语料库
model.train(flatten_corpus, total_examples=model.corpus_count, epochs=10)
embeddings = model.wv.get_normed_vectors()

2. 词嵌入输出示例

array([[-0.01744956, -0.11224882,  0.13236344, ...,  0.0972883 ,
         0.02966034, -0.04626285],
       [ 0.05841004, -0.00941145, -0.07332838, ..., -0.07433803,
         0.02825699, -0.12789766],
       [ 0.10318288, -0.08702228, -0.14564443, ...,  0.1026295 ,
         0.01967871,  0.03213153],
       ...,
       [-0.03165161,  0.08460254, -0.05135883, ..., -0.00983593,
         0.08976564,  0.01239256],
       [-0.04694653,  0.12579133, -0.03276197, ..., -0.02105372,
         0.08431913, -0.0318971 ],
       [ 0.03841057,  0.03328352, -0.05580311, ...,  0.04187248,
        -0.03482581, -0.02766625]], dtype=float32)

3. 平均Word2Vec计算代码

ls = []
avg_embeddings = []
for i in range(len(flatten_corpus)):
    
    if len(flatten_corpus[i]) != 0:
    
        for j in range(len(flatten_corpus[i])):

            if len(flatten_corpus[j]) != 0:

                if len(flatten_corpus[i][j]) != 0:
                    ls.append(model.wv[flatten_corpus[i][j]].tolist())


        ls = list(chain.from_iterable(ls))

        avg_embeddings.append(sum(ls)/len(flatten_corpus[i]))
        ls = []

4. 相似度计算代码及错误

执行以下代码时:

cosine_similarity(np.array(avg_embeddings[idx]).reshape(1, -1), np.array(avg_embeddings).reshape(1, -1))

出现维度不兼容错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[702], line 1
----> 1 cosine_similarity(np.array(avg_embeddings[idx]).reshape(1, -1), np.array(avg_embeddings).reshape(1, -1))

File ~/anaconda3/lib/python3.10/site-packages/sklearn/metrics/pairwise.py:1393, in cosine_similarity(X, Y, dense_output)
   1358 """Compute cosine similarity between samples in X and Y.
   1359 
   1360 Cosine similarity, or the cosine kernel, computes similarity as the
   (...)
   1389     Returns the cosine similarity between samples in X and Y.
   1390 """
   1391 # to avoid recursive import
-> 1393 X, Y = check_pairwise_arrays(X, Y)
   1395 X_normalized = normalize(X, copy=True)
   1396 if X is Y:

File ~/anaconda3/lib/python3.10/site-packages/sklearn/metrics/pairwise.py:180, in check_pairwise_arrays(X, Y, precomputed, dtype, accept_sparse, force_all_finite, copy)
    174         raise ValueError(
    175             "Precomputed metric requires shape "
    176             "(n_queries, n_indexed). Got (%d, %d) "
    177             "for %d indexed." % (X.shape[0], X.shape[1], Y.shape[0])
    178         )
    179 elif X.shape[1] != Y.shape[1]:
-> 180     raise ValueError(
    181         "Incompatible dimension for X and Y matrices: "
    182         "X.shape[1] == %d while Y.shape[1] == %d" % (X.shape[1], Y.shape[1])
    183     )
    185 return X, Y

ValueError: Incompatible dimension for X and Y matrices: X.shape[1] == 1 while Y.shape[1] == 4881

当传入两个参数均为avg_embeddings时,输出为:

array([[1.]])  # 预期应该输出4886个相似度值,对应总电影数量

问题分析与解决方法

核心错误点

  1. 平均向量计算逻辑完全错误:

    • 内层循环错误使用flatten_corpus[j]而非flatten_corpus[i][j],导致跨电影取词向量,完全打乱单部电影的标签集合。
    • 用chain.from_iterable(ls)把所有词向量的元素平铺成一维列表,后续sum(ls)是把所有数值相加,再除以电影标签数量,得到的不是300维的平均向量,而是一个标量(单一数值)。这直接导致avg_embeddings里的每个元素都是标量,而非300维向量。
  2. 相似度计算的维度错误:

    • 因为avg_embeddings的元素是标量,所以np.array(avg_embeddings[idx]).reshape(1,-1)得到(1,1)的形状,而np.array(avg_embeddings).reshape(1,-1)是(1, 4881)的形状,维度不匹配引发错误。
    • 传入两个avg_embeddings时,cosine_similarity计算的是两个一维数组的自相似,自然得到1。

修正后的平均向量计算代码

import numpy as np

avg_embeddings = []
for movie_tags in flatten_corpus:
    if not movie_tags:  # 跳过空标签集合
        avg_embeddings.append(np.zeros(300))  # 用零向量填充空标签电影
        continue
    # 收集当前电影所有标签的词向量(过滤不在词表中的标签)
    tag_vectors = [model.wv[tag] for tag in movie_tags if tag in model.wv]
    if not tag_vectors:  # 处理所有标签都不在词表的情况
        avg_embeddings.append(np.zeros(300))
        continue
    # 对300维向量分别求均值,得到当前电影的平均向量
    avg_vec = np.mean(tag_vectors, axis=0)
    avg_embeddings.append(avg_vec)

# 转换为numpy数组方便后续计算
avg_embeddings = np.array(avg_embeddings)

修正后的相似度计算代码

计算某部电影(索引idx)与其他所有电影的余弦相似度:

from sklearn.metrics.pairwise import cosine_similarity

# 取出目标电影的向量,形状为(1, 300)
target_vec = avg_embeddings[idx].reshape(1, -1)
# 计算与所有电影的相似度,结果形状为(1, 4886)
similarities = cosine_similarity(target_vec, avg_embeddings)
print(similarities)

额外说明

  • 训练Word2Vec时使用了get_normed_vectors(),得到的是归一化后的词向量,后续可以对平均向量再做归一化,确保余弦相似度计算的一致性。
  • 处理空标签或标签不在词表的情况很重要,避免出现计算错误或缺失值。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:07:02