我对编程很新,之前从未使用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.]]
如果我用上面的代码计算余弦相似度,则第1行([0])返回0.45112924,第4行返回0.14177624和0.70710678([3])。
out_file.txt
0 0.796001425306
1 nan
2 nan
3 0.856981065776
4 nan
我非常感谢对我提问的任何帮助或建议!
答案 0 :(得分:2)
您可以考虑使用scipy
代替。但是,它没有采用稀疏矩阵输入。你必须提供numpy数组。
import scipy.sparse as sp
from scipy.spatial.distance import cdist
X = np.random.randn(10000, 10000)
D = cdist(X, X.T, metric='cosine') # cosine distance matrix between 2 columns
这是10000 x 10000随机数组的速度。
%timeit cdist(X, X.T, metric='cosine')
16.4 s ± 325 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
尝试小阵列
X = np.array([[1,0,1], [0, 3, 2], [1,0,1]])
D = cdist(X, X.T, metric='cosine')
这将给出
[[ 1.11022302e-16 1.00000000e+00 4.22649731e-01]
[ 6.07767730e-01 1.67949706e-01 9.41783727e-02]
[ 1.11022302e-16 1.00000000e+00 4.22649731e-01]]
例如D[0, 2]
是第0列和第2列之间的余弦距离
from numpy.linalg import norm
1 - np.dot(X[:, 0], X[:,2])/(norm(X[:, 0]) * norm(X[:,2])) # give 0.422649