def test_invalid_inputs(self):
        input_value = constant_op.constant([-0.8, -0.5, 0, 0.3, 0.8, -2.0],
                                           shape=(6, ),
                                           dtype=dtypes.float32),
        input_min = constant_op.constant(-127, shape=(), dtype=dtypes.float32)
        input_max = constant_op.constant(127, shape=(), dtype=dtypes.float32)
        # Tensor with invalid shape and invalid number of elements.
        num_bits = constant_op.constant([], shape=(0, ), dtype=dtypes.int32)

        # Test that running the op raises error. It raises different errors
        # depending on whether the shape inference is run first or the op's
        # Compute() is run first.
        try:
            array_ops.quantize_and_dequantize_v3(input_value,
                                                 input_min,
                                                 input_max,
                                                 num_bits,
                                                 signed_input=True)
        except Exception as ex:  # pylint: disable=broad-except
            if isinstance(ex, errors.InvalidArgumentError):
                self.assertRegex(str(ex),
                                 "The `num_bits` tensor should be a scalar.")
            elif isinstance(ex, ValueError):
                self.assertRegex(str(ex), "Shape must be rank 0")
            else:
                self.fail(
                    "Raised exception other than expected: %s. "
                    "Expected exceptions are errors.InvalidArgumentError or ValueError",
                    ex.__name__)
        else:
            self.fail(
                "Did not raise an exception where it is expected to raise either "
                "a ValueError or errors.InvalidArgumentError.")
Example #2
0
 def quantize_and_dequantize_v3(x):
     return array_ops.quantize_and_dequantize_v3(x,
                                                 -127,
                                                 127,
                                                 num_bits=8,
                                                 signed_input=True,
                                                 range_given=False)
Example #3
0
def _FakeQuantWithMinMaxVars(inputs,
                             min_var,
                             max_var,
                             per_channel,
                             num_bits,
                             narrow_range,
                             use_qdq=False):
    """Adds a fake quantization operation.

  Depending on value of per_channel, this operation may do global quantization
  or per channel quantization.  min_var and max_var should have corresponding
  shapes: [1] when per_channel == False and [d] when per_channel == True.

  Args:
    inputs: a tensor containing values to be quantized.
    min_var: a variable containing quantization range lower end(s).
    max_var: a variable containing quantization range upper end(s).
    per_channel: a boolean specifying whether to use per-channel quantization.
    num_bits: Number of bits to use for quantization, must be between 2 and 8.
    narrow_range: Whether to use the narrow quantization range
      [1; 2^num_bits - 1] or wide range [0; 2^num_bits - 1].
    use_qdq: Use tf.quantize_and_dequantize_v3 op instead of fake_quant_with_min_max_vars
      for quantization. The qdq op is used for scaling with no zero point.
  Returns:
    a tensor containing quantized values.
  """

    if per_channel:
        assert len(min_var.get_shape()) == 1
        assert len(max_var.get_shape()) == 1
        return array_ops.fake_quant_with_min_max_vars_per_channel(
            inputs,
            min_var,
            max_var,
            num_bits=num_bits,
            narrow_range=narrow_range)
    else:
        assert min_var.get_shape() == []  # pylint: disable=g-explicit-bool-comparison
        assert max_var.get_shape() == []  # pylint: disable=g-explicit-bool-comparison
        if use_qdq:
            return array_ops.quantize_and_dequantize_v3(inputs,
                                                        min_var,
                                                        max_var,
                                                        num_bits=num_bits)

        return array_ops.fake_quant_with_min_max_vars(
            inputs,
            min_var,
            max_var,
            num_bits=num_bits,
            narrow_range=narrow_range)
    def test_valid(self):
        with ops.Graph().as_default(), context.eager_mode():
            input_value = constant_op.constant([-0.8, -0.5, 0, 0.3, 0.8, -2.0],
                                               shape=(6, ),
                                               dtype=dtypes.float32),
            input_min = constant_op.constant(-127,
                                             shape=(),
                                             dtype=dtypes.float32)
            input_max = constant_op.constant(127,
                                             shape=(),
                                             dtype=dtypes.float32)
            num_bits = constant_op.constant(8, shape=(), dtype=dtypes.int32)

            quantized = array_ops.quantize_and_dequantize_v3(input_value,
                                                             input_min,
                                                             input_max,
                                                             num_bits,
                                                             signed_input=True,
                                                             range_given=False)
            self.assertSequenceAlmostEqual(input_value[0].numpy(),
                                           quantized.numpy()[0],
                                           delta=0.05)
Example #5
0
 def quantize_and_dequantize_v3(x):
   return array_ops.quantize_and_dequantize_v3(
       x, -127, 127, num_bits=8, signed_input=True, range_given=False)