Esempio n. 1
0
  def testAddOp(self, tf_quantization_mode):
    root = tracking.AutoTrackable()
    root.add_func = def_function.function(lambda x: x + x)
    input_data = tf.reshape(tf.range(4, dtype=tf.float32), [1, 4])
    concrete_func = root.add_func.get_concrete_function(input_data)

    # Convert model and check if the op is not flex.
    converter = lite.TFLiteConverterV2.from_concrete_functions([concrete_func],
                                                               root)
    converter._experimental_tf_quantization_mode = tf_quantization_mode
    tflite_model = converter.convert()
    self.assertTrue(tflite_model)
    if tf_quantization_mode == 'LEGACY_INTEGER':
      self.assertIn('ADD', tflite_test_util.get_ops_list(tflite_model))
    else:
      self.assertIn('FlexAddV2', tflite_test_util.get_ops_list(tflite_model))

    # Check the model works.
    interpreter = Interpreter(model_content=tflite_model)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    test_input = np.array([[1.0, 2.0, 3.0, 4.0]], dtype=np.float32)
    interpreter.set_tensor(input_details[0]['index'], test_input)
    interpreter.invoke()

    output_details = interpreter.get_output_details()
    expected_output = np.array([[2.0, 4.0, 6.0, 8.0]], dtype=np.float32)
    output_data = interpreter.get_tensor(output_details[0]['index'])
    self.assertTrue((expected_output == output_data).all())
Esempio n. 2
0
    def testFlexWithDoubleOp(self):
        # Create a graph that has one double op.
        saved_model_dir = os.path.join(self.get_temp_dir(), 'model2')
        with ops.Graph().as_default():
            with session.Session() as sess:
                in_tensor = array_ops.placeholder(shape=[1, 4],
                                                  dtype=dtypes.int32,
                                                  name='input')
                out_tensor = double_op.double(in_tensor)
                inputs = {'x': in_tensor}
                outputs = {'z': out_tensor}
                saved_model.simple_save(sess, saved_model_dir, inputs, outputs)

        converter = lite.TFLiteConverterV2.from_saved_model(saved_model_dir)
        converter.target_spec.supported_ops = set([lite.OpsSet.SELECT_TF_OPS])
        converter.target_spec.experimental_select_user_tf_ops = ['Double']
        tflite_model = converter.convert()
        self.assertTrue(tflite_model)
        self.assertIn('FlexDouble',
                      tflite_test_util.get_ops_list(tflite_model))

        # Check the model works with TensorFlow ops.
        interpreter = Interpreter(model_content=tflite_model)
        interpreter.allocate_tensors()
        input_details = interpreter.get_input_details()
        test_input = np.array([[1.0, 2.0, 3.0, 4.0]], dtype=np.int32)
        interpreter.set_tensor(input_details[0]['index'], test_input)
        interpreter.invoke()

        output_details = interpreter.get_output_details()
        expected_output = np.array([[2.0, 4.0, 6.0, 8.0]], dtype=np.int32)
        output_data = interpreter.get_tensor(output_details[0]['index'])
        self.assertTrue((expected_output == output_data).all())
Esempio n. 3
0
  def testL2LossOp(self, tf_quantization_mode):
    root = tracking.AutoTrackable()
    root.l2_loss_func = def_function.function(lambda x: nn_ops.l2_loss(x))  # pylint: disable=unnecessary-lambda
    input_data = tf.range(4, dtype=tf.float32)
    concrete_func = root.l2_loss_func.get_concrete_function(input_data)

    converter = lite.TFLiteConverterV2.from_concrete_functions([concrete_func],
                                                               root)
    converter._experimental_tf_quantization_mode = tf_quantization_mode
    tflite_model = converter.convert()
    self.assertTrue(tflite_model)
    self.assertIn('FlexL2Loss', tflite_test_util.get_ops_list(tflite_model))

    # Check the model works.
    interpreter = Interpreter(model_content=tflite_model)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    test_input = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float32)
    interpreter.set_tensor(input_details[0]['index'], test_input)
    interpreter.invoke()

    output_details = interpreter.get_output_details()
    expected_output = np.array([15.0], dtype=np.float32)
    output_data = interpreter.get_tensor(output_details[0]['index'])
    self.assertTrue((expected_output == output_data).all())
Esempio n. 4
0
    def _run(self,
             flags_str,
             should_succeed,
             expected_ops_in_converted_model=None,
             expected_output_shapes=None):
        output_file = os.path.join(self.get_temp_dir(), 'model.tflite')
        tflite_bin = resource_loader.get_path_to_datafile('tflite_convert')
        cmdline = '{0} --output_file={1} {2}'.format(tflite_bin, output_file,
                                                     flags_str)

        exitcode = os.system(cmdline)
        if exitcode == 0:
            with gfile.Open(output_file, 'rb') as model_file:
                content = model_file.read()
            self.assertEqual(content is not None, should_succeed)
            if expected_ops_in_converted_model:
                op_set = tflite_test_util.get_ops_list(content)
                for opname in expected_ops_in_converted_model:
                    self.assertIn(opname, op_set)
            if expected_output_shapes:
                output_shapes = tflite_test_util.get_output_shapes(content)
                self.assertEqual(output_shapes, expected_output_shapes)
            os.remove(output_file)
        else:
            self.assertFalse(should_succeed)
Esempio n. 5
0
 def testFlexWithAutomaticPassThrough(self):
   # Create a graph that has one L2Loss op.
   with ops.Graph().as_default():
     with session.Session() as sess:
       in_tensor = array_ops.placeholder(
           shape=[4], dtype=dtypes.float32, name='input')
       out_tensor = nn_ops.l2_loss(in_tensor)
       converter = lite.TFLiteConverter.from_session(sess, [in_tensor],
                                                     [out_tensor])
       converter.target_spec.supported_ops = set([lite.OpsSet.SELECT_TF_OPS])
       converter._experimental_allow_all_select_tf_ops = True
       tflite_model = converter.convert()
   self.assertTrue(tflite_model)
   self.assertIn('FlexL2Loss', tflite_test_util.get_ops_list(tflite_model))
Esempio n. 6
0
  def testConvOpWithBias(self, tf_quantization_mode):

    class ConvModel(tracking.AutoTrackable):

      @def_function.function
      def conv_func(self, in_tensor, filter_tensor):
        bias = constant_op.constant(3., shape=[1])
        conv_tensor = tf.nn.conv2d(
            in_tensor,
            filter_tensor,
            strides=[1, 1, 1, 1],
            dilations=[1, 1, 1, 1],
            padding='VALID',
            data_format='NHWC')
        conv_tensor = conv_tensor + bias
        return tf.nn.relu(conv_tensor)

    root = ConvModel()
    input_data = tf.reshape(tf.range(4, dtype=tf.float32), [1, 2, 2, 1])
    filter_data = tf.reshape(tf.range(2, dtype=tf.float32), [1, 2, 1, 1])
    concrete_func = root.conv_func.get_concrete_function(
        input_data, filter_data)

    converter = lite.TFLiteConverterV2.from_concrete_functions([concrete_func],
                                                               root)
    converter._experimental_tf_quantization_mode = tf_quantization_mode
    tflite_model = converter.convert()
    self.assertTrue(tflite_model)
    self.assertCountEqual(['CONV_2D', 'RESHAPE'],
                          tflite_test_util.get_ops_list(tflite_model))

    # Check the model works.
    interpreter = Interpreter(model_content=tflite_model)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()
    test_input = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float32).reshape(
        (1, 2, 2, 1))
    interpreter.set_tensor(input_details[0]['index'], test_input)
    test_filter = np.array([1.0, 0.0], dtype=np.float32).reshape((1, 2, 1, 1))
    interpreter.set_tensor(input_details[1]['index'], test_filter)
    interpreter.invoke()

    output_details = interpreter.get_output_details()
    expected_output = np.array([[[[4.]], [[6.]]]], dtype=np.float32)
    output_data = interpreter.get_tensor(output_details[0]['index'])
    self.assertTrue((expected_output == output_data).all())
Esempio n. 7
0
  def testFlexWithCustomOp(self):
    new_graph, inputs, outputs = self._createGraphWithCustomOp(
        opname='CustomAdd4')

    # Import to load the custom opdef.
    saved_model_dir = os.path.join(self.get_temp_dir(), 'model')
    with ops.Graph().as_default():
      with session.Session() as sess:
        import_graph_def(new_graph, name='')
        saved_model.simple_save(sess, saved_model_dir, inputs, outputs)

    converter = lite.TFLiteConverterV2.from_saved_model(saved_model_dir)
    converter.target_spec.supported_ops = set([lite.OpsSet.SELECT_TF_OPS])
    converter.target_spec.experimental_select_user_tf_ops = ['CustomAdd4']
    tflite_model = converter.convert()

    self.assertIn('FlexCustomAdd4', tflite_test_util.get_ops_list(tflite_model))
Esempio n. 8
0
def mlir_convert(options, graph_def, input_tensors, output_tensors, **kwargs):
    """Convert a model's graph def into a tflite model with MLIR-based conversion.

  Args:
    options: A lite.testing.generate_examples_lib.Options instance.
    graph_def: A GraphDef object.
    input_tensors: List of input tensor tuples `(name, shape, type)`.
    output_tensors: List of output tensors (names).
    **kwargs: Extra parameters.

  Returns:
    output tflite model, log_txt from conversion
    or None, log_txt if it did not convert properly.
  """
    test_params = kwargs.get("test_params", {})
    # TODO(b/146025965): Rename ExtraTocoOptions to ExtraConvertOptions or
    #                    something else.
    extra_toco_options = kwargs.get("extra_toco_options",
                                    zip_test_utils.ExtraTocoOptions())
    input_arrays = [x[0] for x in input_tensors]
    input_shapes = zip_test_utils.get_input_shapes_map(input_tensors)

    tflite_model = None
    log = ""

    with tempfile.NamedTemporaryFile() as graphdef_file:
        graphdef_file.write(graph_def.SerializeToString())
        graphdef_file.flush()
        converter = tf.lite.TFLiteConverter.from_frozen_graph(
            graphdef_file.name, input_arrays, output_tensors, input_shapes)
        converter.allow_custom_ops = extra_toco_options.allow_custom_ops
        converter.experimental_new_quantizer = options.mlir_quantizer

        if options.run_with_flex:
            converter.supported_ops = set(
                [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS])

        if test_params.get("dynamic_range_quantize", False):
            converter.optimizations = [tf.lite.Optimize.DEFAULT]

        if test_params.get("fully_quantize", False):
            converter.optimizations = [tf.lite.Optimize.DEFAULT]

            # Read the input range for the representative dataset from parameters.
            min_value, max_value = test_params.get("input_range", (-1, 1))

            def representative_dataset(input_tensors):
                calibration_inputs = []
                for _, shape, _ in input_tensors:
                    if shape:
                        dims = [
                            1 if dim.value is None else dim.value
                            for dim in shape.dims
                        ]
                        calibration_inputs.append(
                            np.random.uniform(min_value, max_value,
                                              tuple(dims)).astype(np.float32))
                return calibration_inputs

            def representative_dataset_gen():
                for _ in range(100):
                    yield representative_dataset(input_tensors)

            if test_params.get("quant_16x8", False):
                converter.target_spec.supported_ops = [
                    tf.lite.OpsSet.\
                    EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
                ]
            else:
                converter.target_spec.supported_ops = [
                    tf.lite.OpsSet.TFLITE_BUILTINS_INT8
                ]

            converter.representative_dataset = representative_dataset_gen
            if extra_toco_options.inference_input_type:
                converter.inference_input_type = (
                    extra_toco_options.inference_input_type)

            if extra_toco_options.inference_output_type:
                converter.inference_output_type = (
                    extra_toco_options.inference_output_type)

        try:
            tflite_model = converter.convert()
            if options.expected_ops_in_converted_model:
                ops_list = tflite_test_util.get_ops_list(tflite_model)
                for expected_op in options.expected_ops_in_converted_model:
                    if expected_op not in ops_list:
                        # Force the test to fail.
                        tflite_model = None
                        raise ValueError(
                            "{} op not found in the converted model".format(
                                expected_op))
        except Exception as e:  # pylint: disable=broad-except
            log = str(e)

    return tflite_model, log
Esempio n. 9
0
def mlir_convert(
        options,
        saved_model_dir,
        input_tensors,
        output_tensors,  # pylint: disable=unused-argument
        **kwargs):
    """Convert a saved model into a tflite model with MLIR-based conversion.

  Args:
    options: A lite.testing.generate_examples_lib.Options instance.
    saved_model_dir: Path to the saved model.
    input_tensors: List of input tensor tuples `(name, shape, type)`.
    output_tensors: List of output tensors (names).
    **kwargs: Extra parameters.

  Returns:
    output tflite model, log_txt from conversion
    or None, log_txt if it did not convert properly.
  """
    test_params = kwargs.get("test_params", {})
    # TODO(b/146025965): Rename ExtraTocoOptions to ExtraConvertOptions or
    #                    something else.
    extra_toco_options = kwargs.get("extra_toco_options",
                                    zip_test_utils.ExtraTocoOptions())
    tflite_model = None
    log = ""

    signature_key = signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
    converter = tf.lite.TFLiteConverter.from_saved_model(
        saved_model_dir, [signature_key])
    converter.allow_custom_ops = extra_toco_options.allow_custom_ops
    converter.experimental_new_quantizer = options.mlir_quantizer
    if options.make_tf_ptq_tests:
        if options.hlo_aware_conversion:
            tf_quantization_mode = "DEFAULT"
        else:
            tf_quantization_mode = "LEGACY_INTEGER"
        converter._experimental_tf_quantization_mode = tf_quantization_mode  # pylint: disable=protected-access

    if options.run_with_flex:
        converter.target_spec.supported_ops = set(
            [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS])

    if test_params.get("dynamic_range_quantize", False):
        converter.optimizations = [tf.lite.Optimize.DEFAULT]

    if test_params.get("fully_quantize", False):
        converter.optimizations = [tf.lite.Optimize.DEFAULT]

        # Read the input range for the representative dataset from parameters.
        min_value, max_value = test_params.get("input_range", (-1, 1))

        def representative_dataset(input_tensors):
            calibration_inputs = {}
            for name, shape, dtype in input_tensors:
                if shape:
                    dims = [
                        1 if dim.value is None else dim.value
                        for dim in shape.dims
                    ]
                    calibration_inputs[name] = np.random.uniform(
                        min_value, max_value,
                        tuple(dims)).astype(dtype.as_numpy_dtype)
            return calibration_inputs

        def representative_dataset_gen():
            for _ in range(100):
                yield representative_dataset(input_tensors)

        if test_params.get("quant_16x8", False):
            converter.target_spec.supported_ops = [
                tf.lite.OpsSet.
                EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
            ]
        else:
            converter.target_spec.supported_ops = [
                tf.lite.OpsSet.TFLITE_BUILTINS_INT8
            ]

        converter.representative_dataset = representative_dataset_gen
        if extra_toco_options.inference_input_type:
            converter.inference_input_type = (
                extra_toco_options.inference_input_type)

        if extra_toco_options.inference_output_type:
            converter.inference_output_type = (
                extra_toco_options.inference_output_type)

    try:
        tflite_model = converter.convert()
        if options.expected_ops_in_converted_model:
            ops_list = tflite_test_util.get_ops_list(tflite_model)
            for expected_op in options.expected_ops_in_converted_model:
                if expected_op not in ops_list:
                    # Force the test to fail.
                    tflite_model = None
                    raise ValueError(
                        "{} op not found in the converted model".format(
                            expected_op))
    except Exception as e:  # pylint: disable=broad-except
        log = str(e)

    return tflite_model, log
Esempio n. 10
0
 def testFlexOp(self):
     model_path = resource_loader.get_path_to_datafile(
         '../testdata/softplus_flex.bin')
     op_set = tflite_test_util.get_ops_list(
         gfile.GFile(model_path, 'rb').read())
     self.assertCountEqual(op_set, ['FlexSoftplus'])
Esempio n. 11
0
 def testBuiltinOp(self):
     model_path = resource_loader.get_path_to_datafile(
         '../testdata/add.bin')
     op_set = tflite_test_util.get_ops_list(
         gfile.GFile(model_path, 'rb').read())
     self.assertCountEqual(op_set, ['ADD'])