提问者:小点点

为什么np. astype('uint8')在Windows和Mac上给出不同的结果?


我有一个(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 

共1个答案

匿名用户

这个问题是由于错误的转换导致整数溢出。事实上,Numpy使用C强制转换来转换值,但是将0-255范围之外的浮点数转换为8位无符号整数会导致C中未定义的行为。我们尽力在不影响性能的情况下报告错误,但这并不是在所有情况下都能做到的。Numpy的最新版本应该可以解决这个问题,但问题仍然部分未解决。请参阅1.24.0发行说明,这个问题和这个问题,以及这个PR(AFAIK,这个问题的第一个引用可以在这里找到)。

无论如何,虽然可能无法在目标机器上检测到错误,但将浮点数转换到0-255范围之外是不安全的,您不应该期望得到正确的结果。您需要调整代码,以便首先不会溢出。我还建议您至少使用Numpy的1.24.0版本,以便更好地跟踪此类错误。

相关帖子:为什么numpy处理溢出不一致?