Python中计算numpy矩阵行相似度并查找最相似行的最佳方法
问题描述
我是Python初学者,现有如下类型为numpy.matrix的矩阵(生成矩阵的代码省略):
[[0. 0.2342598 0. 0. 0. 0.31308172 0. 0. 0. 0. 0.31308172 0. 0. 0.86549525 0. ] [0. 0.2342598 0. 0. 0. 0.31308172 0. 0. 0. 0. 0.31308172 0. 0. 0.86549525 0. ] [0.22575551 0.72375361 0. 0.19345532 0.22575551 0.19345532 0. 0.38691064 0.19345532 0.19345532 0.19345532 0.19345532 0. 0. 0. ] [0.22575551 0.72375361 0. 0.19345532 0.22575551 0.19345532 0. 0.38691064 0.19345532 0.19345532 0.19345532 0.19345532 0. 0. 0. ] [0. 0.64936739 0. 0.28928716 0. 0. 0.39985833 0.28928716 0.28928716 0.28928716 0. 0.28928716 0. 0. 0. ] [0.26302218 0.50593649 0.37991833 0.22539002 0.26302218 0. 0.31153847 0.11269501 0.11269501 0.45078005 0. 0.11269501 0.18995916 0. 0.18995916]]
我使用sklearn.metrics.pairwise.cosine_similarity可便捷获取两行的余弦相似度,比如运行cosine_similarity(X[0], X[1])会得到仅含一个元素的numpy.ndarray,该float值介于0.0到1.0之间,代表X[0]和X[1]的相似度,可通过cosine_similarity(X[0], X[1])[0][0].item()提取该数值。
目前我的需求不是仅对比两行相似度,而是要将X[0]和矩阵中其余所有行对比,找出与X[0]最相似的行。我自行实现了循环遍历的计算方法,代码如下:
def calculate(): h = 0.0 e = -1 for i in range(1, len(m)): if cosine_similarity(m[0], m[i])[0][0].item() >= h: h = cosine_similarity(m[0], m[i])[0][0].item() e = i return e
请问有没有更符合Python风格、性能更高、更优雅实用的实现方案?
解答
直接使用cosine_similarity的批量计算能力配合numpy内置方法即可,完全不需要手动写循环:
from sklearn.metrics.pairwise import cosine_similarity import numpy as np def find_most_similar_row(mat): # 边界判断:矩阵行数不足2时无对比意义 if len(mat) <= 1: return -1 # 一次性计算首行和所有行的余弦相似度 sim_array = cosine_similarity(mat[0], mat)[0] # 排除首行自身的匹配,取剩余行相似度最大值的索引,+1修正切片带来的索引偏移 target_idx = sim_array[1:].argmax() + 1 return target_idx
方案优势
- 性能大幅提升:原方案循环N次调用相似度计算接口,存在大量重复的向量归一化计算,且每个循环内重复调用两次接口浪费一倍性能;新方案底层使用numpy向量化运算,仅执行一次批量计算,矩阵规模越大性能优势越明显,万行以上场景速度可提升几十上百倍。
- 代码简洁易读:核心逻辑仅2行,没有冗余的中间变量,完全符合Pythonic的编码风格。
- 结果准确:numpy内置的
argmax方法会自动返回第一个最大值的索引,和你原循环的判断逻辑完全一致。
内容的提问来源于stack exchange,提问作者Life after Guest
相关产品推荐
相关产品推荐

