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

username: SoufSilence
cooked: <p>You can reproduce by codes below.</p>
<pre><code class="lang-auto">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
</code></pre>
<p>The manual calcultaion result is -2016 (-63*32), but the result of posted code is 0.</p>
<pre><code class="lang-auto">tensor([[[[0.]]]], size=(1, 1, 1, 1), dtype=torch.quint8,
       quantization_scheme=torch.per_tensor_affine, scale=32.0, zero_point=0)
</code></pre>
<p>Maybe this is due to data overflow. But i cannot figure it out ( because -2016 &gt; (-64*32)).</p>

username: SoufSilence
cooked: <p>No reply for a long time. Can anyone help??? <img src="https://discuss.pytorch.org/images/emoji/apple/thinking.png?v=9" title=":thinking:" class="emoji" alt=":thinking:"></p>

username: jerryzh168
cooked: <p>yeah maybe it is overflow cc <a class="mention" href="/u/zafar">@Zafar</a> <a class="mention" href="/u/dskhudia">@dskhudia</a></p>

username: dskhudia
cooked: <p>Thanks for reporting.<br>
Actual result should be the following:</p>
<pre><code class="lang-auto">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)
</code></pre>
<pre><code class="lang-auto">-2012
-63
</code></pre>
<p>Will check if it’s a bug. I don’t see any kind of overflow or saturation issue with these xq and Wq.</p>

username: SoufSilence
cooked: <p>Yes, the result is <code>-2012</code> if no round processing is done, <code>-2016</code> is the result after round.<br>
This question has been bothering me for a long time. Looking forward to your reply.</p>

username: dskhudia
cooked: <p><a class="mention" href="/u/soufsilence">@SoufSilence</a>,</p>
<p>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.</p>
<p>If you pick the following numbers (I changed -59 to 59 in w), you get the result as 48.</p>
<pre><code class="lang-auto">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)
</code></pre>
<p>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.</p>

username: SoufSilence
cooked: <p><a class="mention" href="/u/dskhudia">@dskhudia</a>, Thanks for your help.<br>
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.</p>