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

zkure5ic  于 2023-03-08  发布在  Windows
关注(0)|答案(1)|浏览(218)

我有一个(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
以下是不同操作系统、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
igetnqfo

igetnqfo1#

这个问题是由于错误的转换导致整数溢出。实际上,Numpy使用C强制转换来转换值,但是将0 - 255范围之外的浮点数转换为8位无符号整数会导致C中的未定义行为。2在这种情况下,我们尝试尽最大努力报告错误而不影响性能,但这并非在所有情况下都可行。Numpy的最新版本应该可以解决这个问题,但是这个问题仍然没有得到部分解决。请参见1.24.0发行说明this issuethis one,以及this PR(AFAIK,第一个引用这个问题的文件是here)。
无论如何,虽然在你的目标机器上可能检测不到这个错误,但是在0 - 255范围之外转换浮点数是不安全的,你不应该期待一个正确的结果。你需要调整你的代码,这样就不会有溢出。我还建议你至少使用1.24.0版本的Numpy,以便更好地跟踪这样的错误。
相关帖子:Why does numpy handle overflows inconsistently?

相关问题