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

如何高效计算不含自相似与重复项的余弦相似度?

高效计算不含自相似与重复项的余弦相似度

当然有高效的办法解决这个问题!你完全不用先算出完整的相似度矩阵再去清理自相似和重复项——我们可以直接定位到矩阵里的有效区域,一步到位拿到想要的结果。

先回顾下你的初始数据和代码:

import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

data = pd.DataFrame({ 
    'id': [1, 2, 3, 4, 5], 
    'a': [55, 2123, -19.3, 9, -8], 
    'b': [21, -0.1, 0.003, 4, 2.1] 
})

# 原始完整相似度矩阵计算
S = cosine_similarity(data.drop('id', axis=1))

最推荐的方法:利用Numpy三角索引提取有效区域

Numpy的triu_indices_from可以直接帮我们定位到矩阵的上三角区域(不含对角线),这部分正好对应所有不重复的向量对,完全跳过自相似和重复项:

import numpy as np

# 获取上三角区域的索引(k=1表示跳过对角线)
upper_tri_idx = np.triu_indices_from(S, k=1)
# 提取对应的相似度值
sim_values = S[upper_tri_idx]

# 如果需要转换成带ID对的直观DataFrame
id_pairs = [(data['id'][i], data['id'][j]) for i, j in zip(*upper_tri_idx)]
result_df = pd.DataFrame({
    'id_pair': id_pairs,
    'cosine_similarity': sim_values
})

这样得到的result_df里,每一行都是唯一的向量对相似度,没有任何冗余数据。

大数据场景优化:避免计算完整矩阵

如果你的数据集非常大,计算完整的N×N矩阵会浪费内存和计算资源。这时候可以直接只计算需要的向量对:

vectors = data.drop('id', axis=1).values
sim_list = []
pair_list = []

for i in range(len(vectors)):
    # 只计算i之后的向量对,避免重复
    for j in range(i+1, len(vectors)):
        # 计算单对向量的余弦相似度
        single_sim = cosine_similarity([vectors[i]], [vectors[j]])[0][0]
        sim_list.append(single_sim)
        pair_list.append((data['id'][i], data['id'][j]))

result_df = pd.DataFrame({
    'id_pair': pair_list,
    'cosine_similarity': sim_list
})

不过这种循环方式的效率不如Numpy索引方法,因为Numpy是底层优化的向量化操作,数据量越大,差异越明显。

为什么这些方法更高效?

  • 节省内存:不用存储完整的N×N矩阵,只保留需要的部分结果。
  • 减少计算量:第二种方法直接跳过了重复计算,只算一次每对向量的相似度。
  • 无需后续清理:结果直接就是目标数据,不用再做去重、过滤对角线等操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 13:57:30