【发布时间】:2021-04-22 21:03:28
【问题描述】:
我怀疑这是我对这段代码不了解或不了解的非常基本的东西;我唯一的借口是我是python的初学者。
我正在尝试这篇文章中的一些余弦相似度矩阵计算:
What's the fastest way in Python to calculate cosine similarity given sparse matrix data?
其中一个需要计算初始矩阵乘积的对角线的倒数。
假设他的初始矩阵是m,其中每一行代表一个“对象”,其“坐标”在矩阵的列中。所以你想计算行之间的余弦相似度。
然后,要使用矩阵乘积法,您可以执行mp = numpy.dot(m, m.T) 之类的操作。
现在,如果m 中没有只有 0 的行,mp 的对角线永远不会有任何零值,因为它的每个元素都是 @987654327 对应行的平方元素之和@.
我在计算中使用的 m 确实没有全为 0 的行。
事实上,当我这样做时:
mp = np.dot(m, m.T)
mnorms2 = mp.diagonal()
我可以很容易地测试:
mnorms2.min()
# 32
由于我对m 使用稀疏矩阵(csr),所以mp 也是稀疏的,我只需要mnorms2 的特定元素对,我通过以下方式获得:
mp_rows, mp_cols = mp.nonzero()
这些是mnorms2 元素的索引,我需要将它们相乘、取平方根并除以mp.data。
我看到code in the method I was trying经历了所有的中间步骤,但我认为这只是为了说明,所以我尝试一口气完成,比如:
mp.data = mp.data / numpy.sqrt(mnorms2[mp_rows] * mnorms2[mp_cols])
这给出了除以零的错误,尽管我确信mnorms2 的任何元素都不为零!
更糟糕的是,它并没有系统地这样做,而只是针对一些m 的,尽管在所有情况下这些矩阵都具有相似的稀疏结构和内容。
事实上我什至做到了:
denom = numpy.sqrt(mnorms2[mp_rows] * mnorms2[mp_cols])
我发现:
denom.min()
# 0.0
两个没有 0 的数组的(逐个元素)乘积怎么会有 0?
最后唯一起作用的是:
inv = 1 / numpy.sqrt(mnorms2[mp_rows])
inv = inv / numpy.sqrt(mnorms2[mp_cols])
mp.data = mp.data * inv
我真的不明白为什么一步一步的工作,而'all in one go'方法会导致错误,因为最终操作应该是相同的。
显然发生了一些奇怪的事情,因为当我尝试这个时:
mnorms2[0:5]
# array([71, 73, 77, 68, 72], dtype=uint8)
mnorms2[0:5] * mnorms2[0:5]
# array([177, 209, 41, 16, 64], dtype=uint8)
177 不是 71 的平方...:/
这是怎么回事?
有什么建议/想法吗?
谢谢!
【问题讨论】:
-
71的平方不能用uint8表示。尝试使用例如 dtype='uint32' 来初始化 mnorms2。
标签: python sparse-matrix cosine-similarity