【问题标题】:unexpected division by zero error when dividing by the product of two arrays in python在python中除以两个数组的乘积时意外除以零错误
【发布时间】: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


【解决方案1】:

我认为问题出在dtype

uint8 : 无符号整数(0 到 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)

【讨论】:

  • 谢谢!我确实怀疑...但我认为dtype 会在完成需要不同操作的操作时自行更改(例如np.sqrt 似乎这样做)。给你一些背景信息,之所以有这个奇怪的dtype,是因为我从一个二进制矩阵开始,它编码特征的存在和不存在(参见stackoverflow.com/questions/67158157/…)。在更正行/列交换之后,可能更容易使用 stackoverflow.com/a/46501473/6376297
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多