TensorFlow Lite モデルへのメタデータの追加

TensorFlow Lite メタデータは、モデルを記述するための標準を提供します。メタデータは、モデルの内容と入出力情報に関する重要な知識源です。メタデータはメタデータと

Kaggle モデルで公開されているすべての画像モデルには、メタデータが入力されています。

メタデータ形式のモデル

model_with_metadata
図 1. メタデータと関連ファイルを含む TFLite モデル。

モデル メタデータは、FlatBuffer ファイルである metadata_schema.fbs で定義されます。図 1 に示すように、TFLite モデルスキーマmetadata フィールドに "TFLITE_METADATA" という名前で保存されます。分類ラベルファイルなど、一部のモデルには関連ファイルが付属している場合があります。これらのファイルは、ZipFile の「追加」モード'a' モード)を使用して、ZIP として元のモデルファイルの末尾に連結されます。TFLite インタープリタは、以前と同じ方法で新しいファイル形式を使用できます。詳しくは、関連ファイルをパッケージ化するをご覧ください。

メタデータの入力、可視化、読み取り方法については、以下の説明をご覧ください。

メタデータ ツールを設定する

モデルにメタデータを追加する前に、TensorFlow を実行するための Python プログラミング環境を設定する必要があります。設定方法の詳細については、こちらをご覧ください。

Python プログラミング環境を設定したら、追加のツールをインストールする必要があります。

pip install tflite-support

TensorFlow Lite メタデータ ツールは Python 3 をサポートしています。

Flatbuffers Python API を使用してメタデータを追加する

スキーマのモデル メタデータは 3 つの部分で構成されています。

  1. モデル情報 - モデルの全体的な説明とライセンス条項などの項目。ModelMetadata をご覧ください。
    1. 入力情報 - 入力と、正規化などの必要な前処理の説明。SubGraphMetadata.input_tensor_metadata をご覧ください。
      1. 出力情報 - ラベルへのマッピングなど、必要な出力と後処理の説明。SubGraphMetadata.output_tensor_metadata をご覧ください。

この時点で TensorFlow Lite は単一のサブグラフのみをサポートしているため、TensorFlow Lite コード生成ツールAndroid Studio ML バインディング機能は、メタデータを表示してコードを生成するときに、SubGraphMetadata.nameSubGraphMetadata.description ではなく ModelMetadata.nameModelMetadata.description を使用します。

サポートされている入出力タイプ

入出力用の TensorFlow Lite メタデータは、特定のモデルタイプではなく、入力タイプと出力タイプを念頭に置いて設計されています。入力型と出力型が以下、または以下の組み合わせで構成されている限り、モデルの機能にかかわらず、TensorFlow Lite メタデータでサポートされます。

  • 特徴 - 符号なし整数または float32 の数値。
  • 画像 - 現在、メタデータでは RGB とグレースケールの画像がサポートされています。
  • 境界ボックス - 長方形の境界ボックス。スキーマは、さまざまな番号付けスキームをサポートしています。

関連ファイルをパッケージ化する

TensorFlow Lite モデルには、さまざまな関連ファイルが含まれている場合があります。たとえば、自然言語モデルには通常、単語の一部を単語 ID にマッピングする語彙ファイルがあります。分類モデルには、オブジェクト カテゴリを示すラベルファイルがあります。関連ファイルがないと(存在する場合)、モデルはうまく機能しません。

これで、メタデータ Python ライブラリを介して関連ファイルをモデルにバンドルできるようになりました。新しい TensorFlow Lite モデルは、モデルと関連ファイルの両方を含む zip ファイルになります。一般的な zip ツールで展開できます。この新しいモデル形式では、引き続き同じファイル拡張子 .tflite が使用されます。既存の TFLite フレームワークおよびインタープリタと互換性があります。詳細については、メタデータと関連ファイルをモデルにパッケージ化するをご覧ください。

関連付けられたファイルの情報をメタデータに記録できます。ファイル形式と添付場所(ModelMetadataSubGraphMetadataTensorMetadata など)に応じて、TensorFlow Lite Android コード生成ツールは、対応する前処理と後処理をオブジェクトに自動的に適用できます。詳細については、スキーマの各アソシエイト ファイル タイプの <Codegen usage> セクションをご覧ください。

正規化パラメータと量子化パラメータ

正規化は、ML でよく使用されるデータ前処理手法です。正規化の目的は、値の範囲の差を歪めずに値を共通のスケールに変更することです。

モデルの量子化は、重みの表現精度を下げ、必要に応じて保存と計算の両方を有効化できる手法です。

前処理と後処理に関して、正規化と量子化は 2 つの独立したステップです。詳しくは以下をご覧ください。

正規化 量子化

浮動小数点モデルと量子モデルにおける MobileNet の入力画像のパラメータ値の例。
浮動小数点モデル:
- 平均: 127.5
- std: 127.5
量子モデル:
- 平均: 127.5
- std: 127.5
浮動小数点モデル:
- zeroPoint: 0
- scale: 1.0
量子モデル:
- zeroPoint: 128.0
- scale:0.0078125f




呼び出すタイミング


入力: トレーニングで入力データが正規化される場合、推論の入力データもそれに応じて正規化する必要があります。
出力: 通常、出力データは正規化されません。
浮動小数点モデルでは量子化は必要ありません。
量子化モデルでは、前処理と後処理で量子化が必要な場合と必要ない場合があります。入出力テンソルのデータ型によって異なります。
- 浮動小数点テンソル。前処理と後処理で量子化する必要はありません。量子演算と逆数演算はモデルグラフに組み込まれています。
- int8 / uint8 テンソル: 前処理と後処理で量子化が必要です。


数式


normalized_input = (入力 - 平均) / std
入力の量子化:
q = f / scale + zeroPoint
出力の逆量子化:
f = (q - zeroPoint) * scale

パラメータの場所
モデル作成者によって入力され、モデルのメタデータに NormalizationOptions として保存されます。 TFLite コンバータによって自動的に入力され、tflite モデルファイルに格納されます。
パラメータの取得方法 MetadataExtractor API 経由 [2] TFLite Tensor API [1] または MetadataExtractor API [2] 経由
浮動小数点モデルと量子モデルは同じ値を共有しますか? はい。浮動小数点モデルと量子モデルは 正規化パラメータが同じです いいえ、浮動小数点モデルでは量子化は必要ありません。
TFLite コード生成ツールまたは Android Studio ML バインディングは、データ処理時に自動的に生成しますか?
はい

はい

[1] TensorFlow Lite Java APITensorFlow Lite C++ API
[2] メタデータ エクストラクタ ライブラリ

uint8 モデルで画像データを処理するときに、正規化と量子化がスキップされることがあります。ピクセル値が [0, 255] の範囲内であれば問題ありません。ただし一般的には、該当する場合は、正規化パラメータと量子化パラメータに従って常にデータを処理する必要があります。

さまざまなタイプのモデルにメタデータを入力する方法の例を以下に示します。

画像分類

スクリプトをこちらからダウンロードしてください。このスクリプトにより、mobilenet_v1_0.75_160_quantized.tflite にメタデータが入力されます。次のようにスクリプトを実行します。

python ./metadata_writer_for_image_classifier.py \
    --model_file=./model_without_metadata/mobilenet_v1_0.75_160_quantized.tflite \
    --label_file=./model_without_metadata/labels.txt \
    --export_directory=model_with_metadata

他の画像分類モデルのメタデータを入力するには、こちらのようなモデル仕様をスクリプトに追加します。このガイドの残りの部分では、画像分類の例の重要なセクションのいくつかを取り上げ、主な要素について説明します。

画像分類の例を詳しく学ぶ

モデル情報

メタデータは、新しいモデル情報の作成から始まります。

from tflite_support import flatbuffers
from tflite_support import metadata as _metadata
from tflite_support import metadata_schema_py_generated as _metadata_fb

""" ... """
"""Creates the metadata for an image classifier."""

# Creates model info.
model_meta = _metadata_fb.ModelMetadataT()
model_meta.name = "MobileNetV1 image classifier"
model_meta.description = ("Identify the most prominent object in the "
                          "image from a set of 1,001 categories such as "
                          "trees, animals, food, vehicles, person etc.")
model_meta.version = "v1"
model_meta.author = "TensorFlow"
model_meta.license = ("Apache License. Version 2.0 "
                      "http://www.apache.org/licenses/LICENSE-2.0.")

入出力情報

このセクションでは、モデルの入力シグネチャと出力シグネチャを記述する方法について説明します。このメタデータは、前処理および後処理のコードを作成するために、自動コード生成ツールで使用できます。テンソルに関する入力または出力の情報を作成するには:

# Creates input info.
input_meta = _metadata_fb.TensorMetadataT()

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()

画像入力

画像は ML の一般的な入力タイプです。TensorFlow Lite メタデータは、色空間などの情報と、正規化などの前処理情報をサポートします。画像の寸法は、入力テンソルの形状によってすでに指定され、自動的に推定できるため、手動で指定する必要はありません。

input_meta.name = "image"
input_meta.description = (
    "Input image to be classified. The expected image is {0} x {1}, with "
    "three channels (red, blue, and green) per pixel. Each value in the "
    "tensor is a single byte between 0 and 255.".format(160, 160))
input_meta.content = _metadata_fb.ContentT()
input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
input_meta.content.contentProperties.colorSpace = (
    _metadata_fb.ColorSpaceType.RGB)
input_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.ImageProperties)
input_normalization = _metadata_fb.ProcessUnitT()
input_normalization.optionsType = (
    _metadata_fb.ProcessUnitOptions.NormalizationOptions)
input_normalization.options = _metadata_fb.NormalizationOptionsT()
input_normalization.options.mean = [127.5]
input_normalization.options.std = [127.5]
input_meta.processUnits = [input_normalization]
input_stats = _metadata_fb.StatsT()
input_stats.max = [255]
input_stats.min = [0]
input_meta.stats = input_stats

ラベル出力

ラベルは、TENSOR_AXIS_LABELS を使用して、関連ファイルを介して出力テンソルにマッピングできます。

# Creates output info.
output_meta = _metadata_fb.TensorMetadataT()
output_meta.name = "probability"
output_meta.description = "Probabilities of the 1001 labels respectively."
output_meta.content = _metadata_fb.ContentT()
output_meta.content.content_properties = _metadata_fb.FeaturePropertiesT()
output_meta.content.contentPropertiesType = (
    _metadata_fb.ContentProperties.FeatureProperties)
output_stats = _metadata_fb.StatsT()
output_stats.max = [1.0]
output_stats.min = [0.0]
output_meta.stats = output_stats
label_file = _metadata_fb.AssociatedFileT()
label_file.name = os.path.basename("your_path_to_label_file")
label_file.description = "Labels for objects that the model can recognize."
label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
output_meta.associatedFiles = [label_file]

メタデータ フラットバッファを作成する

次のコードは、モデル情報と入力情報と出力情報を結合します。

# Creates subgraph info.
subgraph = _metadata_fb.SubGraphMetadataT()
subgraph.inputTensorMetadata = [input_meta]
subgraph.outputTensorMetadata = [output_meta]
model_meta.subgraphMetadata = [subgraph]

b = flatbuffers.Builder(0)
b.Finish(
    model_meta.Pack(b),
    _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
metadata_buf = b.Output()

メタデータと関連ファイルをモデルにパックする

メタデータ フラットバッファが作成されると、メタデータとラベルファイルが populate メソッドを使用して TFLite ファイルに書き込まれます。

populator = _metadata.MetadataPopulator.with_model_file(model_file)
populator.load_metadata_buffer(metadata_buf)
populator.load_associated_files(["your_path_to_label_file"])
populator.populate()

load_associated_files を使用すると、必要な数の関連ファイルをモデルにパックできます。ただし、少なくともメタデータに文書化されているファイルをパックする必要があります。この例では、ラベルファイルのパッキングが必須です。

メタデータを可視化する

Netron を使用してメタデータを可視化するか、MetadataDisplayer を使用して TensorFlow Lite モデルから JSON 形式にメタデータを読み取ることができます。

displayer = _metadata.MetadataDisplayer.with_model_file(export_model_path)
export_json_file = os.path.join(FLAGS.export_directory,
                                os.path.splitext(model_basename)[0] + ".json")
json_file = displayer.get_metadata_json()
# Optional: write out the metadata as a json file
with open(export_json_file, "w") as f:
  f.write(json_file)

Android Studio は、Android Studio の ML バインディング機能を使用してメタデータを表示することもできます。

メタデータのバージョニング

メタデータ スキーマは、スキーマ ファイルの変更を追跡するセマンティック バージョニング番号と、実際のバージョンの互換性を示す Flatbuffers ファイル識別によってバージョニングされます。

セマンティック バージョン番号

メタデータ スキーマは、MAJOR.MINOR.PATCH などのセマンティック バージョニング番号でバージョニングされます。こちらのルールに従ってスキーマの変更を追跡します。バージョン 1.0.0 の後に追加されたフィールドの履歴をご覧ください。

Flatbuffers ファイルの識別

セマンティック バージョニングは、ルールに従う場合に互換性を保証しますが、真の非互換性を意味しません。MAJOR の数値を高くしても、必ずしも下位互換性が損なわれているわけではありません。したがって、メタデータ スキーマの真の互換性を示すために、フラットバッファのファイル識別情報である file_identifier を使用します。ファイル識別子の長さは 4 文字です。特定のメタデータ スキーマに固定されており、ユーザーが変更することはありません。メタデータ スキーマの下位互換性がなんらかの理由で失われる必要がある場合、file_identifier は、たとえば「M001」から「M002」に引き上げられます。File_identifier は、metadata_version よりも大幅に変更されることが少なくなります。

最低限必要なメタデータ パーサーのバージョン

最低限必要なメタデータ パーサー バージョンは、メタデータ フラットバッファ全体を読み取ることができるメタデータ パーサー(フラットバッファで生成されたコード)の最小バージョンです。バージョンは、入力されたすべてのフィールドのバージョンの中で最大のバージョン番号であり、ファイル識別子で示される最小の互換バージョンです。最低限必要なメタデータ パーサー バージョンは、メタデータが TFLite モデルに挿入されるときに、MetadataPopulator によって自動的に入力されます。必要最小限のメタデータ パーサー バージョンの使用方法については、メタデータ エクストラクタをご覧ください。

モデルからメタデータを読み取る

メタデータ エクストラクタ ライブラリは、さまざまなプラットフォームのモデルからメタデータと関連ファイルを読み取ることができる便利なツールです(Java バージョンC++ バージョンをご覧ください)。Flatbuffers ライブラリを使用して、他の言語で独自のメタデータ抽出ツールを構築できます。

Java でのメタデータの読み取り

Android アプリでメタデータ エクストラクタ ライブラリを使用する場合は、MavenCentral でホストされている TensorFlow Lite メタデータ AAR を使用することをおすすめします。MetadataExtractor クラスだけでなく、メタデータ スキーマモデルスキーマの FlatBuffers Java バインディングも含まれます。

これは、build.gradle 依存関係で次のように指定できます。

dependencies {
    implementation 'org.tensorflow:tensorflow-lite-metadata:0.1.0'
}

夜間スナップショットを使用するには、Sonatype スナップショット リポジトリが追加されていることを確認します。

モデルを指す ByteBuffer を使用して MetadataExtractor オブジェクトを初期化できます。

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer は、MetadataExtractor オブジェクトの存続期間中、変更されない必要があります。モデル メタデータの Flatbuffers ファイル ID がメタデータ パーサーの ID と一致しない場合、初期化が失敗する可能性があります。詳細については、メタデータのバージョニングをご覧ください。

ファイル識別子が一致すると、メタデータ エクストラクタは、フラットバッファの上位互換性と下位互換性のメカニズムにより、過去と将来のすべてのスキーマから生成されたメタデータを正常に読み取ります。ただし、古いメタデータ エクストラクタでは、将来のスキーマのフィールドを抽出できません。メタデータの最低限必要なパーサー バージョンは、メタデータ フラットバッファ全体を読み取ることができるメタデータ パーサーの最小バージョンを示します。次の方法を使用して、必要最小限のパーサー バージョン条件が満たされているかどうかを確認できます。

public final boolean isMinimumParserVersionSatisfied();

メタデータなしでモデルを渡すこともできます。ただし、メタデータから読み取るメソッドを呼び出すと、ランタイム エラーが発生します。モデルにメタデータがあるかどうかを確認するには、hasMetadata メソッドを呼び出します。

public boolean hasMetadata();

MetadataExtractor には、入出力テンソルのメタデータを取得するための便利な関数が用意されています。たとえば、

public int getInputTensorCount();
public TensorMetadata getInputTensorMetadata(int inputIndex);
public QuantizationParams getInputTensorQuantizationParams(int inputIndex);
public int[] getInputTensorShape(int inputIndex);
public int getoutputTensorCount();
public TensorMetadata getoutputTensorMetadata(int inputIndex);
public QuantizationParams getoutputTensorQuantizationParams(int inputIndex);
public int[] getoutputTensorShape(int inputIndex);

TensorFlow Lite モデルスキーマは複数のサブグラフをサポートしていますが、TFLite インタープリタは現在、1 つのサブグラフのみをサポートしています。したがって、MetadataExtractor はメソッドの入力引数としてサブグラフ インデックスを省略します。

モデルから関連ファイルを読み取る

メタデータと関連ファイルを含む TensorFlow Lite モデルは、基本的には、一般的な zip ツールで展開して関連ファイルを取得できる ZIP ファイルです。たとえば、次のように mobilenet_v1_0.75_160_quantized を解凍し、モデル内のラベルファイルを抽出できます。

$ unzip mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
Archive:  mobilenet_v1_0.75_160_quantized_1_metadata_1.tflite
 extracting: labels.txt

関連付けられたファイルは、メタデータ エクストラクタ ライブラリから読み取ることもできます。

Java では、ファイル名を MetadataExtractor.getAssociatedFile メソッドに渡します。

public InputStream getAssociatedFile(String fileName);

同様に、C++ では ModelMetadataExtractor::GetAssociatedFile メソッドを使用します。

tflite::support::StatusOr<absl::string_view> GetAssociatedFile(
      const std::string& filename) const;