使用 numpy 操作使用 pytorch 的量化张量再现算术
Reproducing arithmetic with pytorch's quantized tensors with numpy operations
我想知道我必须执行哪些精确的算术运算才能在 pytorch 中重现量化运算的结果。
这几乎是重复的问题:
I want to use Numpy to simulate the inference process of a quantized MobileNet V2 network, but the outcome is different with pytorch realized one
但我什至会用添加两个量化张量的例子来简化它。
例如,在 Resnet 架构中添加两个量化张量,我使用 nn.quantized.FloatFunctional().
self.skip_add = nn.quantized.FloatFunctional()
在推理过程中,我可以通过
添加两个张量
out1 = self.skip_add.add(x1, x2)
其中 x1 和 x2 是 torch.Tensor 类型的张量,在 post 训练量化过程中使用 fbgemm 后端进行量化。
我预计 out2_int = x1.int_repr() + x2.int_repr()
应该与 out1.int_repr()
相同(可能需要在所需范围内进行限制)。
然而事实并非如此。
下面我转储示例输出。
所以我想知道如何通过整数运算得到 out1?
>print(x1)
...,
[-0.0596, -0.0496, -0.1390, ..., -0.0596, -0.0695, -0.0099],
[-0.0893, 0.0000, -0.0695, ..., 0.0596, -0.0893, -0.0298],
[-0.1092, 0.0099, 0.0000, ..., -0.0397, -0.0794, -0.0199]]]],
size=(1, 256, 14, 14), dtype=torch.quint8,
quantization_scheme=torch.per_tensor_affine, scale=0.009925744496285915,
zero_point=75)
print(x2)
...,
[ 0.1390, -0.1669, -0.0278, ..., -0.2225, -0.0556, -0.1112],
[ 0.0000, -0.1669, -0.0556, ..., 0.0556, 0.1112, -0.2781],
[ 0.1390, 0.1669, 0.0278, ..., 0.2225, 0.4171, 0.0834]]]],
size=(1, 256, 14, 14), dtype=torch.quint8,
quantization_scheme=torch.per_tensor_affine, scale=0.02780967578291893,
zero_point=61)
print(x1.int_repr())
...,
[69, 70, 61, ..., 69, 68, 74],
[66, 75, 68, ..., 81, 66, 72],
[64, 76, 75, ..., 71, 67, 73]]]], dtype=torch.uint8)
print(x2.int_repr())
...,
[66, 55, 60, ..., 53, 59, 57],
[61, 55, 59, ..., 63, 65, 51],
[66, 67, 62, ..., 69, 76, 64]]]], dtype=torch.uint8)
打印(out1)
...,
[ 0.0904, -0.2109, -0.1808, ..., -0.2712, -0.1205, -0.1205],
[-0.0904, -0.1808, -0.1205, ..., 0.1205, 0.0301, -0.3013],
[ 0.0301, 0.1808, 0.0301, ..., 0.1808, 0.3314, 0.0603]]]],
size=(1, 256, 14, 14), dtype=torch.quint8,
quantization_scheme=torch.per_tensor_affine, scale=0.03012925386428833,
zero_point=56)
print(out1.int_repr())
...,
[59, 49, 50, ..., 47, 52, 52],
[53, 50, 52, ..., 60, 57, 46],
[57, 62, 57, ..., 62, 67, 58]]]], dtype=torch.uint8)
print(out2_int)
[135, 125, 121, ..., 122, 127, 131],
[127, 130, 127, ..., 144, 131, 123],
[130, 143, 137, ..., 140, 143, 137]]]], dtype=torch.uint8)
答案是双重的:
- 考虑到 int8 数字引用不同的域,实现了整数运算。卷积(或一般的 matrix-matrix 乘法)是根据这个事实实现的,我在这里的回答 I want to use Numpy to simulate the inference process of a quantized MobileNet V2 network, but the outcome is different with pytorch realized one 对我有用。
- pytorch中的加法是在float中实现的。您需要从 int 转换为 float,进行加法运算,然后再转换回 int。
def manual_addition(xq1_int, scale1, zp1, xq2_int, scale2, zp2,
scale_r, zp_r):
xdq = scale1 * (xq1_int.astype(np.float) - zp1)
ydq = scale2 * (xq2_int.astype(np.float) - zp2)
zdq = xdq + ydq
zq_manual_int = (((zdq / scale_r).round()) + zp_r).round()
return zq_manual_int #clipping might be needed
我想知道我必须执行哪些精确的算术运算才能在 pytorch 中重现量化运算的结果。
这几乎是重复的问题: I want to use Numpy to simulate the inference process of a quantized MobileNet V2 network, but the outcome is different with pytorch realized one
但我什至会用添加两个量化张量的例子来简化它。 例如,在 Resnet 架构中添加两个量化张量,我使用 nn.quantized.FloatFunctional().
self.skip_add = nn.quantized.FloatFunctional()
在推理过程中,我可以通过
添加两个张量out1 = self.skip_add.add(x1, x2)
其中 x1 和 x2 是 torch.Tensor 类型的张量,在 post 训练量化过程中使用 fbgemm 后端进行量化。
我预计 out2_int = x1.int_repr() + x2.int_repr()
应该与 out1.int_repr()
相同(可能需要在所需范围内进行限制)。
然而事实并非如此。
下面我转储示例输出。
所以我想知道如何通过整数运算得到 out1?
>print(x1)
..., [-0.0596, -0.0496, -0.1390, ..., -0.0596, -0.0695, -0.0099], [-0.0893, 0.0000, -0.0695, ..., 0.0596, -0.0893, -0.0298], [-0.1092, 0.0099, 0.0000, ..., -0.0397, -0.0794, -0.0199]]]], size=(1, 256, 14, 14), dtype=torch.quint8, quantization_scheme=torch.per_tensor_affine, scale=0.009925744496285915, zero_point=75)
print(x2)
..., [ 0.1390, -0.1669, -0.0278, ..., -0.2225, -0.0556, -0.1112], [ 0.0000, -0.1669, -0.0556, ..., 0.0556, 0.1112, -0.2781], [ 0.1390, 0.1669, 0.0278, ..., 0.2225, 0.4171, 0.0834]]]], size=(1, 256, 14, 14), dtype=torch.quint8, quantization_scheme=torch.per_tensor_affine, scale=0.02780967578291893, zero_point=61)
print(x1.int_repr())
..., [69, 70, 61, ..., 69, 68, 74], [66, 75, 68, ..., 81, 66, 72], [64, 76, 75, ..., 71, 67, 73]]]], dtype=torch.uint8)
print(x2.int_repr())
..., [66, 55, 60, ..., 53, 59, 57], [61, 55, 59, ..., 63, 65, 51], [66, 67, 62, ..., 69, 76, 64]]]], dtype=torch.uint8)
打印(out1)
..., [ 0.0904, -0.2109, -0.1808, ..., -0.2712, -0.1205, -0.1205], [-0.0904, -0.1808, -0.1205, ..., 0.1205, 0.0301, -0.3013], [ 0.0301, 0.1808, 0.0301, ..., 0.1808, 0.3314, 0.0603]]]], size=(1, 256, 14, 14), dtype=torch.quint8, quantization_scheme=torch.per_tensor_affine, scale=0.03012925386428833, zero_point=56)
print(out1.int_repr())
..., [59, 49, 50, ..., 47, 52, 52], [53, 50, 52, ..., 60, 57, 46], [57, 62, 57, ..., 62, 67, 58]]]], dtype=torch.uint8)
print(out2_int)
[135, 125, 121, ..., 122, 127, 131], [127, 130, 127, ..., 144, 131, 123], [130, 143, 137, ..., 140, 143, 137]]]], dtype=torch.uint8)
答案是双重的:
- 考虑到 int8 数字引用不同的域,实现了整数运算。卷积(或一般的 matrix-matrix 乘法)是根据这个事实实现的,我在这里的回答 I want to use Numpy to simulate the inference process of a quantized MobileNet V2 network, but the outcome is different with pytorch realized one 对我有用。
- pytorch中的加法是在float中实现的。您需要从 int 转换为 float,进行加法运算,然后再转换回 int。
def manual_addition(xq1_int, scale1, zp1, xq2_int, scale2, zp2, scale_r, zp_r): xdq = scale1 * (xq1_int.astype(np.float) - zp1) ydq = scale2 * (xq2_int.astype(np.float) - zp2) zdq = xdq + ydq zq_manual_int = (((zdq / scale_r).round()) + zp_r).round() return zq_manual_int #clipping might be needed