QLinearConv#
Domain:
ai.onnxSince version: 10
The convolution operator consumes a quantized input tensor, its scale and zero point, a quantized filter, its scale and zero point, and output’s scale and zero point, and computes the quantized output. Each scale and zero-point pair must have same shape. It means they must be either scalars (per tensor) or 1-D tensors (per output channel). Each input or output and its related zero point must have same type. When bias is present it must be quantized using scale = input scale * weight scale and zero point as 0.
Inputs
x (T1): Input data tensor from previous layer; has size (N x C x H x W), where N is the batch size, C is the number of channels, and H and W are the height and width. Note that this is for the 2D image. Otherwise the size is (N x C x D1 x D2 … x Dn). Optionally, if dimension denotation is in effect, the operation expects input data tensor to arrive with the dimension denotation of [DATA_BATCH, DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE …].
x_scale (tensor(float)): Scale tensor for input ‘x’. It’s a scalar, which means a per-tensor/layer quantization.
x_zero_point (T1): Zero point tensor for input ‘x’. It’s a scalar, which means a per-tensor/layer quantization.
w (T2): The weight tensor that will be used in the convolutions; has size (M x C/group x kH x kW), where C is the number of channels, and kH and kW are the height and width of the kernel, and M is the number of feature maps. For more than 2 dimensions, the kernel shape will be (M x C/group x k1 x k2 x … x kn), where (k1 x k2 x … kn) is the dimension of the kernel. Optionally, if dimension denotation is in effect, the operation expects the weight tensor to arrive with the dimension denotation of [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, FILTER_SPATIAL, FILTER_SPATIAL …]. X.shape[1] == (W.shape[1] * group) == C (assuming zero based indices for the shape array). Or in other words FILTER_IN_CHANNEL should be equal to DATA_CHANNEL.
w_scale (tensor(float)): Scale tensor for input ‘w’. It could be a scalar or a 1-D tensor, which means a per-tensor/layer or per output channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of output channels (M).
w_zero_point (T2): Zero point tensor for input ‘w’. It could be a scalar or a 1-D tensor, which means a per-tensor/layer or per output channel quantization. If it’s a 1-D tensor, its number of elements should be equal to the number of output channels (M).
y_scale (tensor(float)): Scale tensor for output ‘y’. It’s a scalar, which means a per-tensor/layer quantization.
y_zero_point (T3): Zero point tensor for output ‘y’. It’s a scalar, which means a per-tensor/layer quantization.
B (T4): Optional 1D bias to be added to the convolution, has size of M. Bias must be quantized using scale = x_scale * w_scale and zero_point = 0
Outputs
y (T3): Output data tensor that contains the result of the convolution. The output dimensions are functions of the kernel size, stride size, and pad lengths.
Type Constraints
T1: Constrain input type to 8-bit integer tensor. Allowed types: tensor(int8), tensor(uint8).
T2: Constrain filter type to 8-bit integer tensor. Allowed types: tensor(int8), tensor(uint8).
T3: Constrain output type to 8-bit integer tensor. Allowed types: tensor(int8), tensor(uint8).
T4: Constrain bias type to 32-bit integer tensor. Allowed types: tensor(int32).
Examples#
test_cc_qlinearconv
Node:
QLinearConv(x, x_scale, x_zero_point, w, w_scale, w_zero_point, y_scale, y_zero_point) -> (y)
Inputs:
x: shape=(1, 1, 7, 7), dtype=uint8
[[[[ 0, 4, 8, 12, 16, 20, 24],
[ 28, 32, 36, 40, 44, 48, 52],
[ 56, 60, 64, 68, 72, 76, 80],
[ 84, 88, 92, 96, 100, 104, 108],
[112, 116, 120, 124, 128, 132, 136],
[140, 144, 148, 152, 156, 160, 164],
[168, 172, 176, 180, 184, 188, 192]]]]
x_scale: shape=(), dtype=float32
0.00369205
x_zero_point: shape=(), dtype=uint8
132
w: shape=(1, 1, 1, 1), dtype=uint8
[[[[0]]]]
w_scale: shape=(1,), dtype=float32
[0.00172795]
w_zero_point: shape=(1,), dtype=uint8
[255]
y_scale: shape=(), dtype=float32
0.00162681
y_zero_point: shape=(), dtype=uint8
123
Outputs:
y: shape=(1, 1, 7, 7), dtype=uint8
[[[[255, 251, 247, 243, 239, 235, 231],
[227, 223, 219, 215, 211, 207, 203],
[199, 195, 191, 187, 183, 179, 175],
[171, 167, 163, 159, 155, 151, 147],
[143, 139, 135, 131, 127, 123, 119],
[115, 111, 107, 103, 99, 95, 91],
[ 87, 83, 79, 75, 71, 67, 63]]]]
test_cc_qlinearconv_int8
Node:
QLinearConv(x, x_scale, x_zero_point, w, w_scale, w_zero_point, y_scale, y_zero_point) -> (y)
Inputs:
x: shape=(1, 1, 2, 2), dtype=int8
[[[[10, 20],
[30, 40]]]]
x_scale: shape=(), dtype=float32
0.1
x_zero_point: shape=(), dtype=int8
5
w: shape=(1, 1, 2, 2), dtype=int8
[[[[1, 1],
[1, 1]]]]
w_scale: shape=(1,), dtype=float32
[1.]
w_zero_point: shape=(1,), dtype=int8
[0]
y_scale: shape=(), dtype=float32
1.
y_zero_point: shape=(), dtype=int8
-10
Outputs:
y: shape=(1, 1, 1, 1), dtype=int8
[[[[-2]]]]