当分母元素可能为零时,如何高效地逐元素矩阵除法

3 投票
3 回答
2922 浏览
提问于 2025-04-18 02:34

我正在用 Python 2.7.6 和 numpy 编程。我有两个 numpy 矩阵要进行除法运算,代码是 V/np.dot(W,H)。有时候,除数的某些单元格值会等于 0,这样就会出现运行时错误。我想用一种高效的方法实现安全的除法运算。请问我该如何编写代码,既能进行矩阵除法,又能在除数等于 0 的地方在输出矩阵中放 0 呢?

3 个回答

1

虽然你提到“矩阵”,但我猜你其实想要的是数组,因为你想要逐个元素进行除法运算。我会在一个上下文管理器里进行除法,这样可以避免除以零的错误。然后再对结果进行修正。

# Assume V and D are arrays of the same shape
with np.errstate(divide='ignore'): 
    # division errors suppressed only within this block
    quot = V / D
    quot[D == 0] = 0

我的直觉告诉我,这种方法速度应该很快,因为它大部分时间保持数据的原始形状。不过我从来没有和其他方法进行过比较。

1

简单来说,就是找出分母中为零的元素,然后把它们替换成无穷大

D = np.dot(W,H)
D[D==0] = float('inf')
result = V / D

这种方法比直接用 result = V / D 计算要慢,因为它需要先检查零,使用 D[D==0] = float('inf') 来替换,但随着矩阵大小的增加,性能会有所改善。比如,对于一个30x30的矩阵,它的计算时间是普通方法的三倍,而对于一个250x250的矩阵,时间是普通方法的两倍。随着矩阵规模的进一步增大,时间接近普通方法的1.8倍。此外,这种方法比改变浮点异常处理方式(参考Daryl的回答Adrian的回答)要快大约10%。

需要注意的是,浮点数的精度问题可能导致分母中本该为零的元素实际上并不完全是零,这种情况很容易处理,方法如下:

epsilon = 1e-8
D[np.abs(D)<epsilon] = float('inf')
2

Numpy 其实允许你设置在遇到除以零的错误时该怎么处理,具体可以查看 seterr。我认为这个设置是全局的,也就是说它会影响到整个程序,而不是某个特定的地方。如果这个问题对你来说很重要,你可以在进行安全的除法运算之前和之后设置这个选项。

撰写回答