除以 python 中两个数组的乘积时出现意外除以零错误

unexpected division by zero error when dividing by the product of two arrays in python

我怀疑这是我不知道或不了解这段代码的非常基本的东西;我唯一的借口是我是 python.

的完全初学者

我正在尝试根据此 post:

进行一些余弦相似度矩阵计算

What's the fastest way in Python to calculate cosine similarity given sparse matrix data?

其中一个需要计算初始矩阵乘积的对角线的倒数
假设他的初始矩阵是m,其中每一行代表一个'object',其'coordinates'在矩阵的列中。所以你想计算.
之间的余弦相似度 然后,要使用矩阵乘积法,您可以执行类似 mp = numpy.dot(m, m.T).

的操作

现在,如果 m 中没有只有 0 的行,mp 的对角线永远不会有任何零值,因为它的每个元素都是元素的平方和m.
对应行 我在计算中使用的 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 的平方...:/

这是怎么回事?

有什么建议/想法吗?

谢谢!

我觉得问题是dtype

uint8 : Unsigned integer (0 to 255)

import numpy as np
mnorms2 = np.array([71, 73, 77, 68, 72], dtype='uint8')
mnorms2 * mnorms2
# array([177, 209,  41,  16,  64], dtype=uint8)

但是如果您将 dtype 更改为 np.float64:

mnorms2 = np.array([71, 73, 77, 68, 72], dtype=np.float64)
mnorms2 * mnorms2
# array([5041., 5329., 5929., 4624., 5184.])

要更改 dtype,请执行以下操作:

mnorms2  = mnorms2.astype(np.float64)