【发布时间】:2017-06-01 01:51:34
【问题描述】:
我对编程很陌生,以前从未使用过numpy。
所以,我有一个 19001 x 19001 尺寸的矩阵。它包含很多零,因此相对稀疏。如果行中的项目非零,我编写了一些代码来计算列的成对余弦相似度。我将一行的所有成对相似度值相加,并对它们进行一些数学运算,最后得到矩阵每一行的一个值(见下面的代码)。它做了它应该做的事情,但是在处理大量维度时,它真的很慢。有什么办法可以修改我的代码以提高效率?
import numpy as np
from scipy.spatial.distance import cosine
row_number = 0
out_file = open('outfile.txt', 'w')
for row in my_matrix:
non_zeros = np.nonzero(my_matrix[row_number])[0]
non_zeros = list(non_zeros)
cosine_sim = []
for item in non_zeros:
if len(non_zeros) <= 1:
break
x = non_zeros[0]
y = non_zeros[1]
similarity = 1 - cosine(my_matrix[:, x], my_matrix[:, y])
cosine_sim.append(similarity)
non_zeros.pop(0)
summing = np.sum(cosine_sim)
mean = summing / len(cosine_sim)
log = np.log(mean)
out_file_value = log * -1
out_file.write(str(row_number) + " " + str(out_file_value) + "\n")
if row_number <= 19000:
row_number += 1
else:
break
我知道有一些函数可以实际计算列之间的余弦相似度 (from sklearn.metrics.pairwise import cosine_similarity),所以我试了一下。然而,输出是一样的,但同时我真的很困惑,即使我阅读了这个页面上的文档和帖子,提到了这个问题。
例如:
my_matrix =[[0. 0. 7. 0. 5.]
[0. 0. 11. 0. 0.]
[0. 2. 0. 0. 0.]
[0. 0. 2. 11. 5.]
[0. 0. 5. 0. 0.]]
transposed = np.transpose(my_matrix)
sim_matrix = cosine_similarity(transposed)
# resulting similarity matrix
sim_matrix =[[0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0.14177624 0.45112924]
[0. 0. 0.14177624 1. 0.70710678]
[0. 0. 0.45112924 0.70710678 1.]]
如果我用上面的代码计算余弦相似度,它会返回第一行 ([0]) 的 0.45112924 和第四行 ([3]) 的 0.14177624 和 0.70710678。
out_file.txt
0 0.796001425306
1 nan
2 nan
3 0.856981065776
4 nan
非常感谢对我的问题的任何帮助或建议!
【问题讨论】:
-
不应该是
for row_number, row in enumerate(matrix):在每次循环迭代中更改row_number吗? -
另外,您没有在循环中使用
item。如果在发布之前检查代码是否不一致会更好。 -
@Divakar 我缩进了这些块,这只是一个格式问题,通过将它粘贴到这里发生,所以没什么太严重的;)
-
我认为你的代码坏了,你应该使用你已经找到的库代码。如果做不到这一点,不要在 NumPy 数组上编写 Python 循环。它很慢。编写向量操作,或者如果你不能,使用 Numba。
-
@John Zwinck ja,你是完全正确的,但我的问题是我不明白图书馆的作用,因为它们的结果不同。如果我为一个小型测试矩阵手动计算它,我会得到我的代码输出而不是库的输出,这就是导致我出现问题的原因。