如何在多维点积计算中正确识别相同向量?
多维向量两两余弦相似度计算修正方案
当需要计算两两向量的余弦相似度时,一维场景下直接用点积除以两个向量的范数可以得到正确结果(相同向量输出1),但多维场景(每行代表一个向量)下原代码逻辑错误,无法得到对角元素为1的预期结果。
原一维正确代码
import numpy as np a = np.array([0.8, 0.5]) b = np.array([0.8, 0.5]) x = a @ b / np.linalg.norm(a) / np.linalg.norm(b) print(x) # 输出: 1.0
原多维错误代码及问题
import numpy as np a = np.array([[0.8,0.5],[0.4,1]]) b = np.array([[0.8,0.5],[0.4,1]]) x = a @ b / np.linalg.norm(a) / np.linalg.norm(b) print(x) # 输出: [[0.4097561 0.43902439] [0.35121951 0.58536585]] # 预期输出: [[1 0.43] [0.35 1]](对角元素为1,非对角为对应向量的相似度)
错误原因分析
a @ b是矩阵乘法,不是两两行向量的点积,得到的结果不符合余弦相似度的计算逻辑;np.linalg.norm(a)默认计算整个矩阵的Frobenius范数,而非每行向量的L2范数,导致分母错误。
修正后的代码
import numpy as np a = np.array([[0.8,0.5],[0.4,1]]) b = np.array([[0.8,0.5],[0.4,1]]) # 计算每行向量的L2范数,axis=1指定按行计算,reshape为列向量方便广播 norm_a = np.linalg.norm(a, axis=1).reshape(-1, 1) norm_b = np.linalg.norm(b, axis=1).reshape(-1, 1) # 计算两两行向量的点积:a的每行与b的每行做点积,用a @ b.T实现 dot_product = a @ b.T # 计算余弦相似度矩阵 similarity = dot_product / norm_a / norm_b.T print(np.round(similarity, 2)) # 输出: # [[1. 0.43] # [0.35 1. ]]
关键逻辑说明
np.linalg.norm(a, axis=1):按行计算每个向量的L2范数,得到形状为(n,)的数组,reshape(-1,1)转成(n,1)的列向量,确保后续除法能正确广播;a @ b.T:将b转置后,矩阵乘法的结果中,第(i,j)个元素是a的第i行向量与b的第j行向量的点积,正好对应两两向量的点积需求;- 除法操作利用numpy的广播机制,自动将每个点积元素除以对应两个向量的范数乘积,最终对角元素为相同向量的相似度(值为1),非对角元素为对应向量的余弦相似度。
内容的提问来源于stack exchange,提问作者Zac
相关产品推荐
相关产品推荐

