The result of quantized.Conv2d is different from the manual calculation

You can reproduce by codes below.

import torch
import torch.nn.quantized as nnq
### 1 channel
# inpus act
x = torch.Tensor([[[[3,9,30],[14,4,22],[11,7,5]]]])
xq = torch.quantize_per_tensor(x, scale = 1.0, zero_point = 0, dtype=torch.quint8)
xq.int_repr()
c = nnq.Conv2d(1,1,3)
# weights
weight = torch.Tensor([[[[17,21,-59],[-4,-10,-31],[2,-3,59]]]])
qweight = torch.quantize_per_channel(weight, scales=torch.Tensor([1.0]).to(torch.double), zero_points = torch.Tensor([0]).to(torch.int64), axis=0, dtype=torch.qint8)
c.set_weight_bias(qweight,  torch.Tensor([0.0]))
c.scale = 32.0
c.zero_point = 0
out = c(xq)
out

The manual calcultaion result is -2016 (-63*32), but the result of posted code is 0.

tensor([[[[0.]]]], size=(1, 1, 1, 1), dtype=torch.quint8,
       quantization_scheme=torch.per_tensor_affine, scale=32.0, zero_point=0)

Maybe this is due to data overflow. But i cannot figure it out ( because -2016 > (-64*32)).

No reply for a long time. Can anyone help??? :thinking:

yeah maybe it is overflow cc @Zafar @dskhudia

Thanks for reporting.
Actual result should be the following:

import numpy as np
x = np.array([3, 9, 30, 14, 4, 22, 11, 7, 5], dtype=np.int32)
w = np.array([17, 21, -59, -4, -10, -31, 2, -3, 59], dtype=np.int32)

dotP = np.dot(x, w)
result = round(dotP / c.scale)
print(dotP)
print(result)
-2012
-63

Will check if it’s a bug. I don’t see any kind of overflow or saturation issue with these xq and Wq.

Yes, the result is -2012 if no round processing is done, -2016 is the result after round.
This question has been bothering me for a long time. Looking forward to your reply.

@SoufSilence,

Actual result of the operation is -63 and since output tensor is of type torch.quint8, thus the result need to be in the range [0, 255]. Therefore, -63 gets converted to the nearest number in this range.

If you pick the following numbers (I changed -59 to 59 in w), you get the result as 48.

x = np.array([3, 9, 30, 14, 4, 22, 11, 7, 5], dtype=np.int32)
w = np.array([17, 21, 59, -4, -10, -31, 2, -3, 59], dtype=np.int32)

Actual result of this operation is 47.75 and that gets rounded to 48. Since 48 is in the range [0, 255], it is returned as is.

@dskhudia, Thanks for your help.
This is really the cause of the problem. I didn’t realize that the output activation values had the same quantization type as the input activation values. This was a really careless mistake.

1 Like