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

2024-09-30 04:35:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我怀疑这是一个非常基本的问题,我不知道或不理解这段代码;我唯一的借口是我是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的对角线永远不会有任何零值,因为它的每个元素都是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

我真的不明白为什么一步一步走是有效的,而“一步到位”的方法会导致错误,因为最终的操作应该是相同的

显然有一些奇怪的事情发生了,因为当我尝试这个:

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的平方…:/

这是怎么回事

有什么建议/想法吗

谢谢


Tags: the方法innumpy元素data矩阵mp
1条回答
网友
1楼 · 发布于 2024-09-30 04:35:38

我认为问题是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)

相关问题 更多 >

    热门问题