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