def create_for_inference(cls, model_buffer: bytearray, input_norm_mean: List[float], input_norm_std: List[float], label_file_paths: List[str], score_calibration_md: Optional[ metadata_info.ScoreCalibrationMd] = None): """Creates mandatory metadata for TFLite Support inference. The parameters required in this method are mandatory when using TFLite Support features, such as Task library and Codegen tool (Android Studio ML Binding). Other metadata fields will be set to default. If other fields need to be filled, use the method `create_from_metadata_info` to edit them. Args: model_buffer: valid buffer of the model file. input_norm_mean: the mean value used in the input tensor normalization [1]. input_norm_std: the std value used in the input tensor normalizarion [1]. label_file_paths: paths to the label files [2] in the category tensor. Pass in an empty list, If the model does not have any label file. score_calibration_md: information of the score calibration operation [3] in the classification tensor. Optional if the model does not use score calibration. [1]: https://www.tensorflow.org/lite/convert/metadata#normalization_and_quantization_parameters [2]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L108 [3]: https://github.com/tensorflow/tflite-support/blob/5e0cdf5460788c481f5cd18aab8728ec36cf9733/tensorflow_lite_support/metadata/metadata_schema.fbs#L434 Returns: A MetadataWriter object. """ input_md = metadata_info.InputImageTensorMd( name=_INPUT_NAME, description=_INPUT_DESCRIPTION, norm_mean=input_norm_mean, norm_std=input_norm_std, color_space_type=_metadata_fb.ColorSpaceType.RGB, tensor_type=writer_utils.get_input_tensor_types(model_buffer)[0]) output_category_md = metadata_info.CategoryTensorMd( name=_OUTPUT_CATRGORY_NAME, description=_OUTPUT_CATEGORY_DESCRIPTION, label_files=[ metadata_info.LabelFileMd(file_path=file_path) for file_path in label_file_paths ]) output_score_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_SCORE_NAME, description=_OUTPUT_SCORE_DESCRIPTION, score_calibration_md=score_calibration_md) return cls.create_from_metadata_info( model_buffer, input_md=input_md, output_category_md=output_category_md, output_score_md=output_score_md)
def create_from_metadata_info( cls, model_buffer: bytearray, general_md: Optional[metadata_info.GeneralMd] = None, input_md: Optional[metadata_info.InputAudioTensorMd] = None, output_md: Optional[metadata_info.ClassificationTensorMd] = None): """Creates MetadataWriter based on general/input/output information. Args: model_buffer: valid buffer of the model file. general_md: general infromation about the model. If not specified, default general metadata will be generated. input_md: input audio tensor informaton. If not specified, default input metadata will be generated. output_md: output classification tensor informaton. If not specified, default output metadata will be generated. Returns: A MetadataWriter object. """ if output_md is None: output_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_NAME, description=_OUTPUT_DESCRIPTION) return cls.create_from_metadata_info_for_multihead( model_buffer, general_md, input_md, [output_md])
def create_for_inference(cls, model_buffer: bytearray, sample_rate: int, channels: int, label_file_paths: List[str], score_calibration_md: Optional[ metadata_info.ScoreCalibrationMd] = None): """Creates mandatory metadata for TFLite Support inference. The parameters required in this method are mandatory when using TFLite Support features, such as Task library and Codegen tool (Android Studio ML Binding). Other metadata fields will be set to default. If other fields need to be filled, use the method `create_from_metadata_info` to edit them. Args: model_buffer: valid buffer of the model file. sample_rate: the sample rate in Hz when the audio was captured. channels: the channel count of the audio. label_file_paths: paths to the label files [1] in the classification tensor. Pass in an empty list if the model does not have any label file. score_calibration_md: information of the score calibration operation [2] in the classification tensor. Optional if the model does not use score calibration. [1]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L95 [2]: https://github.com/tensorflow/tflite-support/blob/5e0cdf5460788c481f5cd18aab8728ec36cf9733/tensorflow_lite_support/metadata/metadata_schema.fbs#L434 Returns: A MetadataWriter object. """ # To make Task Library working properly, sample_rate, channels need to be # positive. if sample_rate <= 0: raise ValueError( "sample_rate should be positive, but got {}.".format( sample_rate)) if channels <= 0: raise ValueError( "channels should be positive, but got {}.".format(channels)) input_md = metadata_info.InputAudioTensorMd(_INPUT_NAME, _INPUT_DESCRIPTION, sample_rate, channels) output_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_NAME, description=_OUTPUT_DESCRIPTION, label_files=[ metadata_info.LabelFileMd(file_path=file_path) for file_path in label_file_paths ], tensor_type=writer_utils.get_output_tensor_types(model_buffer)[0], score_calibration_md=score_calibration_md) return cls.create_from_metadata_info(model_buffer, input_md=input_md, output_md=output_md)
def test_create_from_metadata_info_succeeds_for_multihead(self): calibration_file1 = test_utils.create_calibration_file( self.get_temp_dir(), "score_cali_1.txt") calibration_file2 = test_utils.create_calibration_file( self.get_temp_dir(), "score_cali_2.txt") general_md = metadata_info.GeneralMd(name="AudioClassifier") input_md = metadata_info.InputAudioTensorMd( name="audio_clip", sample_rate=_SAMPLE_RATE, channels=_CHANNELS) # The output tensors in the model are: Identity, Identity_1 # Create metadata in a different order to test if MetadataWriter can correct # it. output_head_md_1 = metadata_info.ClassificationTensorMd( name="head1", label_files=[ metadata_info.LabelFileMd("labels_en_1.txt"), metadata_info.LabelFileMd("labels_cn_1.txt") ], score_calibration_md=metadata_info.ScoreCalibrationMd( _metadata_fb.ScoreTransformationType.LOG, _DEFAULT_SCORE_CALIBRATION_VALUE, calibration_file1), tensor_name="Identity_1") output_head_md_2 = metadata_info.ClassificationTensorMd( name="head2", label_files=[ metadata_info.LabelFileMd("labels_en_2.txt"), metadata_info.LabelFileMd("labels_cn_2.txt") ], score_calibration_md=metadata_info.ScoreCalibrationMd( _metadata_fb.ScoreTransformationType.LOG, _DEFAULT_SCORE_CALIBRATION_VALUE, calibration_file2), tensor_name="Identity") writer = ( audio_classifier.MetadataWriter.create_from_metadata_info_for_multihead( test_utils.load_file(_MULTIHEAD_MODEL), general_md, input_md, [output_head_md_1, output_head_md_2])) metadata_json = writer.get_metadata_json() expected_json = test_utils.load_file(_JSON_MULTIHEAD, "r") self.assertEqual(metadata_json, expected_json)
def add_classification_output( self, labels: Labels, score_calibration: Optional[ScoreCalibration] = None, name=_OUTPUT_CLASSIFICATION_NAME, description=_OUTPUT_CLASSIFICATION_DESCRIPTION): """Marks model's next output tensor as a classification head. Example usage: writer.add_classification_output( Labels() .add(['cat', 'dog], 'en') .add(['chat', 'chien], 'fr') .add(['/m/011l78', '/m/031d23'], use_as_category_name=True)) Args: labels: an instance of Labels helper class. score_calibration: an instance of ScoreCalibration helper class. name: Metadata name of the tensor. Note that this is different from tensor name in the flatbuffer. description: human readable description of what the tensor does. Returns: The current Writer instance to allow chained operation. """ calibration_md = None if score_calibration: calibration_md = metadata_info.ScoreCalibrationMd( score_transformation_type=score_calibration. transformation_type, default_score=score_calibration.default_score, file_path=self._export_calibration_file( 'score_calibration.txt', score_calibration.parameters)) idx = len(self._output_mds) label_files = [] for item in labels._labels: # pylint: disable=protected-access label_files.append( metadata_info.LabelFileMd(self._export_labels( item.filename, item.names), locale=item.locale)) output_md = metadata_info.ClassificationTensorMd( name=name, description=description, label_files=label_files, tensor_type=self._output_tensor_type(idx), score_calibration_md=calibration_md, ) self._output_mds.append(output_md) return self
def create_for_inference( cls, model_buffer: bytearray, tokenizer_md: Optional[metadata_info.RegexTokenizerMd], label_file_paths: List[str]): """Creates mandatory metadata for TFLite Support inference. The parameters required in this method are mandatory when using TFLite Support features, such as Task library and Codegen tool (Android Studio ML Binding). Other metadata fields will be set to default. If other fields need to be filled, use the method `create_from_metadata_info` to edit them. Args: model_buffer: valid buffer of the model file. tokenizer_md: information of the tokenizer used to process the input string, if any. Only `RegexTokenizer` [1] is currently supported. If the tokenizer is `BertTokenizer` [2] or `SentencePieceTokenizer` [3], refer to `bert_nl_classifier.MetadataWriter`. [1]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L475 [2]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L436 [3]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L473 label_file_paths: paths to the label files [4] in the classification tensor. Pass in an empty list if the model does not have any label file. [4]: https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L95 Returns: A MetadataWriter object. """ input_md = metadata_info.InputTextTensorMd( name=_INPUT_NAME, description=_INPUT_DESCRIPTION, tokenizer_md=tokenizer_md) output_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_NAME, description=_OUTPUT_DESCRIPTION, label_files=[ metadata_info.LabelFileMd(file_path=file_path) for file_path in label_file_paths ], tensor_type=writer_utils.get_output_tensor_types(model_buffer)[0]) return cls.create_from_metadata_info(model_buffer, input_md=input_md, output_md=output_md)
def create_from_metadata_info( cls, model_buffer: bytearray, general_md: Optional[metadata_info.GeneralMd] = None, input_md: Optional[metadata_info.InputTextTensorMd] = None, output_md: Optional[metadata_info.ClassificationTensorMd] = None): """Creates MetadataWriter based on general/input/output information. Args: model_buffer: valid buffer of the model file. general_md: general information about the model. If not specified, default general metadata will be generated. input_md: input text tensor information, if not specified, default input metadata will be generated. output_md: output classification tensor information, if not specified, default output metadata will be generated. Returns: A MetadataWriter object. """ if general_md is None: general_md = metadata_info.GeneralMd( name=_MODEL_NAME, description=_MODEL_DESCRIPTION) if input_md is None: input_md = metadata_info.InputTextTensorMd( name=_INPUT_NAME, description=_INPUT_DESCRIPTION) if output_md is None: output_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_NAME, description=_OUTPUT_DESCRIPTION) if output_md.associated_files is None: output_md.associated_files = [] tokenizer_files = [] if input_md.tokenizer_md: tokenizer_files = writer_utils.get_tokenizer_associated_files( input_md.tokenizer_md.create_metadata().options) return super().create_from_metadata_info( model_buffer=model_buffer, general_md=general_md, input_md=[input_md], output_md=[output_md], associated_files=[ file.file_path for file in output_md.associated_files ] + tokenizer_files)
def test_create_metadata_should_succeed(self, tensor_type, golden_json): label_file_en = metadata_info.LabelFileMd( file_path=self._LABEL_FILE_EN, locale="en") label_file_cn = metadata_info.LabelFileMd( file_path=self._LABEL_FILE_CN, locale="cn") tesnor_md = metadata_info.ClassificationTensorMd( name=self._NAME, description=self._DESCRIPTION, label_files=[label_file_en, label_file_cn], tensor_type=tensor_type) tensor_metadata = tesnor_md.create_metadata() metadata_json = _metadata.convert_to_json( _create_dummy_model_metadata(tensor_metadata)) expected_json = test_utils.load_file(golden_json, "r") self.assertEqual(metadata_json, expected_json)
def create_from_metadata_info( cls, model_buffer: bytearray, general_md: Optional[metadata_info.GeneralMd] = None, input_md: Optional[metadata_info.InputImageTensorMd] = None, output_md: Optional[metadata_info.ClassificationTensorMd] = None): """Creates MetadataWriter based on general/input/output information. Args: model_buffer: valid buffer of the model file. general_md: general infromation about the model. If not specified, default general metadata will be generated. input_md: input image tensor informaton, if not specified, default input metadata will be generated. output_md: output classification tensor informaton, if not specified, default output metadata will be generated. Returns: A MetadataWriter object. """ if general_md is None: general_md = metadata_info.GeneralMd( name=_MODEL_NAME, description=_MODEL_DESCRIPTION) if input_md is None: input_md = metadata_info.InputImageTensorMd( name=_INPUT_NAME, description=_INPUT_DESCRIPTION, color_space_type=_metadata_fb.ColorSpaceType.RGB) if output_md is None: output_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_NAME, description=_OUTPUT_DESCRIPTION) if output_md.associated_files is None: output_md.associated_files = [] return super().create_from_metadata_info( model_buffer=model_buffer, general_md=general_md, input_md=[input_md], output_md=[output_md], associated_files=[ file.file_path for file in output_md.associated_files ])
def test_create_metadata_should_succeed(self, tensor_type, golden_json): label_file_en = metadata_info.LabelFileMd( file_path=self._LABEL_FILE_EN, locale="en") label_file_cn = metadata_info.LabelFileMd( file_path=self._LABEL_FILE_CN, locale="cn") score_calibration_md = metadata_info.ScoreCalibrationMd( _metadata_fb.ScoreTransformationType.IDENTITY, self._CALIBRATION_DEFAULT_SCORE, self._SCORE_CALIBRATION_FILE) tesnor_md = metadata_info.ClassificationTensorMd( name=self._NAME, description=self._DESCRIPTION, label_files=[label_file_en, label_file_cn], tensor_type=tensor_type, score_calibration_md=score_calibration_md) tensor_metadata = tesnor_md.create_metadata() metadata_json = _metadata.convert_to_json( _create_dummy_model_metadata_with_tensor(tensor_metadata)) expected_json = test_utils.load_file(golden_json, "r") self.assertEqual(metadata_json, expected_json)
def create_from_metadata_info( cls, model_buffer: bytearray, general_md: Optional[metadata_info.GeneralMd] = None, input_md: Optional[metadata_info.InputImageTensorMd] = None, output_location_md: Optional[metadata_info.TensorMd] = None, output_category_md: Optional[ metadata_info.CategoryTensorMd] = None, output_score_md: Union[ None, metadata_info.TensorMd, metadata_info.ClassificationTensorMd] = None, output_number_md: Optional[metadata_info.TensorMd] = None): """Creates MetadataWriter based on general/input/outputs information. Args: model_buffer: valid buffer of the model file. general_md: general infromation about the model. input_md: input image tensor informaton. output_location_md: output location tensor informaton. The location tensor is a multidimensional array of [N][4] floating point values between 0 and 1, the inner arrays representing bounding boxes in the form [top, left, bottom, right]. output_category_md: output category tensor information. The category tensor is an array of N integers (output as floating point values) each indicating the index of a class label from the labels file. output_score_md: output score tensor information. The score tensor is an array of N floating point values between 0 and 1 representing probability that a class was detected. Use ClassificationTensorMd to calibrate score. output_number_md: output number of detections tensor information. This tensor is an integer value of N. Returns: A MetadataWriter object. """ if general_md is None: general_md = metadata_info.GeneralMd( name=_MODEL_NAME, description=_MODEL_DESCRIPTION) if input_md is None: input_md = metadata_info.InputImageTensorMd( name=_INPUT_NAME, description=_INPUT_DESCRIPTION, color_space_type=_metadata_fb.ColorSpaceType.RGB) warn_message_format = ( "The output name isn't the default string \"%s\". This may cause the " "model not work in the TFLite Task Library since the tensor name will " "be used to handle the output order in the TFLite Task Library.") if output_location_md is None: output_location_md = metadata_info.TensorMd( name=_OUTPUT_LOCATION_NAME, description=_OUTPUT_LOCATION_DESCRIPTION) elif output_location_md.name != _OUTPUT_LOCATION_NAME: logging.warning(warn_message_format, _OUTPUT_LOCATION_NAME) if output_category_md is None: output_category_md = metadata_info.CategoryTensorMd( name=_OUTPUT_CATRGORY_NAME, description=_OUTPUT_CATEGORY_DESCRIPTION) elif output_category_md.name != _OUTPUT_CATRGORY_NAME: logging.warning(warn_message_format, _OUTPUT_CATRGORY_NAME) if output_score_md is None: output_score_md = metadata_info.ClassificationTensorMd( name=_OUTPUT_SCORE_NAME, description=_OUTPUT_SCORE_DESCRIPTION, ) elif output_score_md.name != _OUTPUT_SCORE_NAME: logging.warning(warn_message_format, _OUTPUT_SCORE_NAME) if output_number_md is None: output_number_md = metadata_info.TensorMd( name=_OUTPUT_NUMBER_NAME, description=_OUTPUT_NUMBER_DESCRIPTION) elif output_number_md.name != _OUTPUT_NUMBER_NAME: logging.warning(warn_message_format, _OUTPUT_NUMBER_NAME) # Create output tensor group info. group = _metadata_fb.TensorGroupT() group.name = _GROUP_NAME group.tensorNames = [ output_location_md.name, output_category_md.name, output_score_md.name ] # Gets the tensor inidces of tflite outputs and then gets the order of the # output metadata by the value of tensor indices. For instance, if the # output indices are [601, 599, 598, 600], tensor names and indices aligned # are: # - location: 598 # - category: 599 # - score: 600 # - number of detections: 601 # because of the op's ports of TFLITE_DETECTION_POST_PROCESS # (https://github.com/tensorflow/tensorflow/blob/a4fe268ea084e7d323133ed7b986e0ae259a2bc7/tensorflow/lite/kernels/detection_postprocess.cc#L47-L50). # Thus, the metadata of tensors are sorted in this way, according to # output_tensor_indicies correctly. output_tensor_indices = _get_tflite_outputs(model_buffer) metadata_list = [ _create_location_metadata(output_location_md), _create_metadata_with_value_range(output_category_md), _create_metadata_with_value_range(output_score_md), output_number_md.create_metadata() ] # Align indices with tensors. sorted_indices = sorted(output_tensor_indices) indices_to_tensors = dict(zip(sorted_indices, metadata_list)) # Output metadata according to output_tensor_indices. output_metadata = [ indices_to_tensors[i] for i in output_tensor_indices ] # Create subgraph info. subgraph_metadata = _metadata_fb.SubGraphMetadataT() subgraph_metadata.inputTensorMetadata = [input_md.create_metadata()] subgraph_metadata.outputTensorMetadata = output_metadata subgraph_metadata.outputTensorGroups = [group] # Create model metadata model_metadata = general_md.create_metadata() model_metadata.subgraphMetadata = [subgraph_metadata] b = flatbuffers.Builder(0) b.Finish(model_metadata.Pack(b), _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER) associated_files = [] _extend_new_files(associated_files, output_category_md.associated_files) _extend_new_files(associated_files, output_score_md.associated_files) return cls(model_buffer, b.Output(), associated_files=associated_files)