【发布时间】:2021-11-14 07:16:55
【问题描述】:
我将两个 float64 矩阵与以下值相乘:
import numpy as np
# 4x5 matrix with identical columns.
x = np.zeros((4, 5,), dtype=np.float64)
x[1] = 1
x[3] = -3
w = np.array([1, 1, -1, 1 / 3], dtype=np.float64)
# The result should be an array of size 5 with equal values.
result = np.matmul(w, x)
print(x)
>>>
[[ 0. 0. 0. 0. 0.]
[ 1. 1. 1. 1. 1.]
[ 0. 0. 0. 0. 0.]
[-3. -3. -3. -3. -3.]]
print(w)
>>> [ 1. 1. -1. 0.33333333]
print(result)
>>> [5.55111512e-17 5.55111512e-17 5.55111512e-17 5.55111512e-17 0.00000000e+00]
result 数组应该包含相同的值,因为每个项目都是具有相同列的w 数组的点积。但是,最后一项是 0.0,与其他非常接近 0 的值不同。这对下游计算有很大影响。
我猜这与 1/3 的值有关,因为用 1/2 替换它会得到稳定的结果。但是如何解决这种不稳定性?
附加信息,因为问题不会在所有机器上重现
我在 MacOS 上使用 numpy 1.18.2 和 Python 3.7.3。 该问题在另一台运行具有相同 Python 和 numpy 版本的 Ubuntu 的机器上重现。
【问题讨论】:
-
我在 google colab 上运行了相同的代码,它给出了
result的预期值。 -
虽然我觉得这很有趣,但是如果这对下游有很大的影响,那么你实际上有更大的问题,我会说你的算法通常不可信。
-
计算机内存中的@NurL 位表示 2 的幂。一些数字,如 1/4,可以在不损失精度的情况下存储,一些 (1/3) 必须稍微四舍五入以适应这种表示.确切的舍入误差取决于 CPU,有时还取决于操作系统(或者更确切地说,它附带的编译器)。在某些情况下,这些小的舍入误差足以影响最终结果。根据问题,可能有办法解决这个问题,例如通过使用对数刻度值来代替
-
@Marat:不,这不是浮点数的本质。浮点数的性质不会导致相同的计算产生不同的结果。必须发生的事情是
numpy没有以简单的定义方式计算matmul,即对行与列进行点积。它必须在做其他事情,涉及对不同位置的不同计算,并导致不同的结果。同样的情况也发生在整数运算中,就好像有人试图用7/3*3和7*3/3计算7/3•3。
标签: python arrays numpy floating-point matrix-multiplication