Numpy与PyTorch浮点精度疑问:float32转换后数值不一致
问题描述
我定义了一个NumPy矩阵a:
>>> a array([[ 1.920941165 , 0.9518795607, 1.5358781432], [-0.2418292026, 0.0851087409, -0.2760766872], [-0.4161812806, 0.7409229185, -0.3248560283], [-0.3439163186, 1.4052927665, -1.612850871 ], [ 1.5810794171, 1.1820622504, 1.8063415367]])
将其类型转换为float32后得到:
>>> a.astype(np.float32) array([[ 1.9209411 , 0.95187956, 1.5358782 ], [-0.2418292 , 0.08510874, -0.27607667], [-0.41618127, 0.7409229 , -0.32485604], [-0.34391633, 1.4052927 , -1.6128509 ], [ 1.5810794 , 1.1820623 , 1.8063415 ]], dtype=float32)
将原始矩阵a转为PyTorch tensor时,能保留原始数值:
>>> torch.tensor(a) tensor([[ 1.9209411650, 0.9518795607, 1.5358781432], [-0.2418292026, 0.0851087409, -0.2760766872], [-0.4161812806, 0.7409229185, -0.3248560283], [-0.3439163186, 1.4052927665, -1.6128508710], [ 1.5810794171, 1.1820622504, 1.8063415367]], dtype=torch.float64)
但将转换为float32的矩阵转为PyTorch tensor时,得到的浮点数值与原float32矩阵不一致:
>>> torch.tensor(a.astype(np.float32)) tensor([[ 1.9209411144, 0.9518795609, 1.5358781815], [-0.2418292016, 0.0851087421, -0.2760766745], [-0.4161812663, 0.7409229279, -0.3248560429], [-0.3439163268, 1.4052927494, -1.6128509045], [ 1.5810793638, 1.1820622683, 1.8063415289]])
请问为何转换为float32的矩阵对应的PyTorch tensor无法与该float32矩阵数值相等?
原因分析
这种差异并不是数值真的不相等,而是浮点数的显示规则和存储特性导致的视觉差异,核心原因有两点:
显示精度的格式化差异:
NumPy在输出float32类型数据时,默认会将数值格式化到7-8位有效数字,相当于做了截断或四舍五入;而PyTorch在显示时会输出更多小数位,把float32对应的十进制近似值完整展开。比如NumPy显示的1.9209411和PyTorch显示的1.9209411144,本质是同一个float32二进制值的不同格式化结果。float32的二进制存储限制:
float32只有23位有效尾数,绝大多数十进制小数无法被精确存储,只能以最接近的二进制近似值保存。NumPy显示的是简化后的近似字符串,PyTorch则展示了更精确的十进制展开,但二者底层存储的二进制浮点数是完全一致的。
验证方法
要确认两者数值是否真的相等,不要只看显示结果,可以用以下方法:
- 使用
np.allclose(a.astype(np.float32), torch.tensor(a.astype(np.float32)).numpy()),结果会返回True,说明数值在浮点误差范围内完全一致。 - 查看底层的二进制编码:将NumPy的float32数组和PyTorch的float32 tensor都转换为uint32类型,会得到完全相同的整数编码,证明存储的二进制值一致。
内容的提问来源于Stack Exchange,提问作者Ankur Goswami
相关产品推荐
相关产品推荐

