Skip to content

Commit

Permalink
feat: implement QuantizedUnfold
Browse files Browse the repository at this point in the history
  • Loading branch information
tguerand committed Feb 2, 2024
1 parent c646736 commit 93313df
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 33 deletions.
4 changes: 1 addition & 3 deletions src/concrete/ml/onnx/ops_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -2077,7 +2077,6 @@ def numpy_expand(x: numpy.ndarray, shape: Optional[Tuple[int]] = None) -> Tuple[
def numpy_unfold(
x: numpy.ndarray,
*,
ceil_mode: int,
kernel_shape: Tuple[int, ...],
pads: Tuple[int, ...] = None,
strides: Tuple[int, ...] = None,
Expand All @@ -2090,7 +2089,6 @@ def numpy_unfold(
Args:
x (numpy.ndarray): input data (many dtypes are supported). Shape is N x C x H x W for 2d
ceil_mode (int): ONNX rounding parameter, expected 0 (torch style dimension computation)
kernel_shape (Tuple[int, ...]): shape of the kernel. Should have 2 elements for 2d conv
pads (Tuple[int, ...]): padding in ONNX format (begin, end) on each axis
strides (Tuple[int, ...]): stride of the convolution on each axis
Expand Down Expand Up @@ -2135,7 +2133,7 @@ def numpy_unfold(
kernels = numpy.concatenate(numpy.array(kernels_list), axis=0)

# Pad the input tensor
pool_pads = compute_onnx_pool_padding(x.shape, kernel_shape, pads, strides, ceil_mode)
pool_pads = compute_onnx_pool_padding(x.shape, kernel_shape, pads, strides, ceil_mode=0)
q_input_pad = numpy_onnx_pad(x, pool_pads)

# Compute the kernels of input values for each kernel position
Expand Down
20 changes: 1 addition & 19 deletions src/concrete/ml/quantization/quantized_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2507,7 +2507,6 @@ def __init__(
)

# Get the ONNX parameters
self.ceil_mode = attrs.get("ceil_mode", None)
self.kernel_shape = attrs.get("kernel_shape", None)
self.pads = attrs.get("pads", tuple([0] * 2 * (len(self.kernel_shape) - 2)))
self.dilations = attrs.get("dilations", tuple([1] * len(self.kernel_shape)))
Expand Down Expand Up @@ -2565,7 +2564,7 @@ def q_impl(

# Compute padding with floor and apply it to the input, pad with the input zero-point
pool_pads = compute_onnx_pool_padding(
q_input.qvalues.shape, self.kernel_shape, self.pads, self.strides, 0
q_input.qvalues.shape, self.kernel_shape, self.pads, self.strides, ceil_mode=0
)

# Can only pad with scalar zero-points, but zero-points can be float in special cases
Expand All @@ -2574,23 +2573,6 @@ def q_impl(
pad_value = int(q_input.quantizer.zero_point)
q_input_pad = numpy_onnx_pad(q_input.qvalues, pool_pads, pad_value, int_only=True)

if self.ceil_mode == 1:
# Padding for TensorFlow style

# Compute padding with ceil and apply it to the input, pad with zeros, the zeros
# will be ignored in the computation
pool_pads_ceil = compute_onnx_pool_padding(
q_input.qvalues.shape, self.kernel_shape, self.pads, self.strides, 1
)

# Can only pad with scalar zero-points, but zero-points can be float in special cases
# for output layers
q_input_pad_ceil = numpy_onnx_pad(q_input.qvalues, pool_pads_ceil, 0, True)

# Copy the PyTorch style padded input to the larger 0 padded tensor
q_input_pad_ceil[:, :, 0 : q_input_pad.shape[2], 0 : q_input_pad.shape[3]] = q_input_pad
q_input_pad = q_input_pad_ceil

# Remark that here, we are _not_ using Concrete pad, since it would pad with
# 0's while we want to pad with zero-point's. So, instead, he have done the padding
# on our side, with q_input_pad
Expand Down
14 changes: 3 additions & 11 deletions tests/quantization/test_quantized_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1993,56 +1993,48 @@ def test_quantized_shape(shape):
(3, 3),
(2, 2),
(0, 0, 0, 0),
0,
),
(
numpy.random.uniform(low=-1.2, high=0.2, size=(10, 1, 16, 16)),
(2, 2),
(1, 1),
(0, 0, 0, 0),
0,
),
(
numpy.random.uniform(low=-2.0, high=2.0, size=(2, 32, 4, 4)),
(2, 2),
(1, 1),
(0, 0, 0, 0),
0,
),
(
numpy.random.uniform(low=-2.0, high=2.0, size=(2, 32, 4, 4)),
(2, 4),
(1, 1),
(1, 2, 1, 2),
1,
),
(
numpy.random.uniform(low=-2.0, high=2.0, size=(2, 32, 4, 4)),
(2, 4),
(1, 1),
(0, 2, 0, 2),
1,
),
(
numpy.random.uniform(low=-2.0, high=2.0, size=(2, 32, 5, 5)),
(3, 3),
(1, 1),
(1, 1, 1, 1),
1,
),
(
numpy.random.uniform(low=-2.0, high=2.0, size=(2, 1, 7, 5)),
(5, 1),
(1, 1),
(1, 2, 0, 4),
1,
),
( # this test fails because of padding
(
numpy.random.uniform(low=-2.0, high=2.0, size=(1, 1, 16, 16)),
(2, 2),
(4, 4),
(1, 2, 0, 4),
1,
),
],
)
Expand All @@ -2051,7 +2043,7 @@ def test_quantized_unfold(params, n_bits, is_signed, check_r2_score, check_float
"""Test the quantized average pool operator."""

# Retrieve arguments
net_input, kernel_shape, strides, pads, ceil_mode = params
net_input, kernel_shape, strides, pads = params

# Create quantized data
q_input = QuantizedArray(n_bits, net_input, is_signed=is_signed)
Expand All @@ -2062,7 +2054,7 @@ def test_quantized_unfold(params, n_bits, is_signed, check_r2_score, check_float
strides=strides,
pads=pads,
kernel_shape=kernel_shape,
ceil_mode=ceil_mode,
# ceil_mode=ceil_mode,
input_quant_opts=q_input.quantizer.quant_options,
)

Expand Down

0 comments on commit 93313df

Please sign in to comment.