我有一个(1000,1000,3)
形状的numpy数组(dtype='float32'
),当我将其转换为dtype='uint8'
时,我在Windows和Mac上得到不同的结果。
数组可在这里:https://www.dropbox.com/s/jrs4n2ayh86s0fn/image.npy?dl=0
在Mac上
>>> import numpy as np
>>> X = np.load('image.npy')
>>> X = X.astype('uint8')
>>> X.sum()
167942490
在windows
>>> import numpy as np
>>> X = np.load('image.npy')
>>> X = X.astype('uint8')
>>> X.sum()
323510676
也使用此数组重现:
import numpy as np
X = np.array([
[[46410., 42585., 32640.],
[45645., 41820., 31875.],
[45390., 41310., 32130.]],
[[44880., 41055., 31110.],
[44115., 40290., 30345.],
[46410., 42330., 33150.]],
[[45390., 41310., 32130.],
[46155., 42075., 32895.],
[42840., 38760., 30090.]]], dtype=np.float32)
print(X.sum(), X.astype('uint8').sum())
在Windows上打印1065135.0 2735
,在Mac上打印1065135.0 1860
。
以下是不同OS和Python和Numpy的结果:
Python 3.8.8 (Win) Numpy 1.22.4 => 1065135.0 2735
Python 3.10.6 (Mac) Numpy 1.24.2 => 1065135.0 2735
Python 3.7.12 (Mac) Numpy 1.21.6 => 1065135.0 1860
这个问题是由于错误的转换导致整数溢出。事实上,Numpy使用C强制转换来转换值,但是将0-255范围之外的浮点数转换为8位无符号整数会导致C中未定义的行为。我们尽力在不影响性能的情况下报告错误,但这并不是在所有情况下都能做到的。Numpy的最新版本应该可以解决这个问题,但问题仍然部分未解决。请参阅1.24.0发行说明,这个问题和这个问题,以及这个PR(AFAIK,这个问题的第一个引用可以在这里找到)。
无论如何,虽然可能无法在目标机器上检测到错误,但将浮点数转换到0-255范围之外是不安全的,您不应该期望得到正确的结果。您需要调整代码,以便首先不会溢出。我还建议您至少使用Numpy的1.24.0版本,以便更好地跟踪此类错误。
相关帖子:为什么numpy处理溢出不一致?