如何计算DataFrame中所有句子两两配对的余弦相似度
全量句子对余弦相似度计算实现方案
直接用矩阵批量计算替代单条循环计算,8000行数据普通消费级机器10秒内就能出结果,具体步骤如下:
- 首先导入需要的依赖库
import pandas as pd import numpy as np from sklearn.metrics.pairwise import cosine_similarity
- 批量计算全量相似度矩阵
先把存储在DataFrame列里的单个嵌入向量拼成二维矩阵,直接调用cosine_similarity即可一次性输出所有句子两两之间的相似度,不用逐行循环:
# 将embeddings列转换为形状为(样本数, 嵌入维度)的numpy二维矩阵 emb_matrix = np.array(df['embeddings'].tolist()) # 输出的sim_matrix形状为(8000, 8000),sim_matrix[i][j]对应第i个句子和第j个句子的余弦相似度 sim_matrix = cosine_similarity(emb_matrix)
内存占用说明:8000*8000的float64类型矩阵占用内存约490MB,常规笔记本完全可以承载,不需要额外分布式计算资源。
- 组装为要求的三列结构结果
相似度矩阵是对称矩阵,且对角线位置是句子和自身的相似度(值恒为1),直接取上三角非对角位置的索引即可避免重复配对、自身配对的无效数据:
# k=1表示偏移1位,排除对角线自身配对的索引,且i<j保证每对句子仅出现一次 i_idx, j_idx = np.triu_indices_from(sim_matrix, k=1) # 组装结果 result_df = pd.DataFrame({ 'sentence_1': df['content'].iloc[i_idx].values, 'sentence_2': df['content'].iloc[j_idx].values, 'cosine_sim_score': sim_matrix[i_idx, j_idx] })
- 可选优化:过滤低相似度配对
8000条句子的非重复配对总共有约3200万条,如果不需要保留所有配对,可以在组装结果前按相似度阈值过滤,大幅缩减结果体积:
# 示例:仅保留余弦相似度大于0.8的句子对 sim_threshold = 0.8 # 先筛选符合阈值的索引 valid_pair_mask = sim_matrix[i_idx, j_idx] > sim_threshold filtered_result_df = result_df[valid_pair_mask].reset_index(drop=True)
注意:不要用逐行调用cosine_similarity的循环写法,这类写法没有用到矩阵运算的并行优化,8000行数据跑下来可能需要数分钟,远慢于一次性计算全量矩阵的方案。
内容的提问来源于stack exchange,提问作者LikeCoding
相关产品推荐
相关产品推荐

