如何避免NumPy matmul溢出?为何int8转int16仍得错误值
问题代码与输出
import numpy as np x1 = np.arange(0,63, dtype=np.int8).reshape(63,1) x2 = np.arange(0,63, dtype=np.int8).reshape(1,63) o = np.zeros((63,63), dtype=np.int16) o = np.matmul(x1,x2) print(o)
输出:
[[ 0 0 0 ... 0 0 0] [ 0 1 2 ... 60 61 62] [ 0 2 4 ... 120 122 124] ... [ 0 60 120 ... 16 76 -120] [ 0 61 122 ... 76 -119 -58] [ 0 62 124 ... -120 -58 4]]
问题描述
使用np.int8类型创建矩阵x1和x2,二者数值均在int8范围内。执行np.matmul运算后,结果超出int8范围,因此将结果存入int16类型变量,但仍得到错误值,请问这是为什么?
原因分析
numpy的矩阵乘法运算精度由输入数组的 dtype 决定,而非最终赋值的变量类型:
- x1和x2都是int8类型,
np.matmul会默认用int8精度执行乘法运算。int8的取值范围是-128~127,当两个int8数值相乘(比如62*62=3844),结果远超出范围,运算时直接发生溢出截断——数值会被对256取模后映射到int8区间,比如3844%256=4,这就是你看到最后一个元素是4的原因。 - 你提前创建的int16变量
o没有起到作用,因为o = np.matmul(x1,x2)是把已经溢出的int8结果直接赋值给o,此时只是把错误的int8数值转换为int16类型,无法恢复溢出前的正确值。
解决方法
方法1:运算前转换输入数组的 dtype
把x1和x2提前转成int16,让乘法在更高精度下执行:
import numpy as np x1 = np.arange(0,63, dtype=np.int8).reshape(63,1).astype(np.int16) x2 = np.arange(0,63, dtype=np.int8).reshape(1,63).astype(np.int16) o = np.matmul(x1,x2) print(o)
方法2:指定matmul的运算 dtype(numpy 1.20+支持)
直接在np.matmul中指定运算时使用的精度,无需转换输入数组:
import numpy as np x1 = np.arange(0,63, dtype=np.int8).reshape(63,1) x2 = np.arange(0,63, dtype=np.int8).reshape(1,63) o = np.matmul(x1,x2, dtype=np.int16) print(o)
内容的提问来源于stack exchange,提问作者Sristi
相关产品推荐
相关产品推荐

