.. _op_ai_onnx_QLinearConv: QLinearConv =========== - **Domain**: ``ai.onnx`` - **Since 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** .. code-block:: text Node: QLinearConv(x, x_scale, x_zero_point, w, w_scale, w_zero_point, y_scale, y_zero_point) -> (y) .. code-block:: text 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** .. code-block:: text Node: QLinearConv(x, x_scale, x_zero_point, w, w_scale, w_zero_point, y_scale, y_zero_point) -> (y) .. code-block:: text 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]]]]