MLコミュニティデーは11月9日です! TensorFlow、JAXからの更新のために私たちに参加し、より多くの詳細をご覧ください

TensorFlowLiteモデルへのメタデータの追加

TensorFlow Liteメタデータは、モデル記述の標準を提供します。メタデータは、モデルの機能とその入力/出力情報に関する重要な知識源です。メタデータは両方で構成されます

上で公開されているすべての画像モデルTensorFlow Liteはモデルを主催し、 TensorFlowハブは、メタデータが移入されています。

メタデータ形式のモデル

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

モデルのメタデータはで定義されているmetadata_schema.fbsFlatBufferのファイル。図1に示すように、それが中に記憶されたメタデータのフィールドTFLiteモデルスキーマ、名前の下に、 "TFLITE_METADATA" 。一部のモデルは、以下のような関連するファイル、と来るかもしれ分類ラベルファイル。これらのファイルは、ZIPファイル使ってZIPなどオリジナルのモデルファイルの最後に連結されている「追記」モード'a'モード)。 TFLiteインタープリターは、以前と同じ方法で新しいファイル形式を使用できます。参照してくださいパックに関連するファイルを詳細については。

メタデータの入力、視覚化、および読み取りの方法については、以下の手順を参照してください。

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

モデルにメタデータを追加する前に、TensorFlowを実行するためのPythonプログラミング環境をセットアップする必要があります。これを設定する方法についての詳細なガイドがあり、ここでは

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

pip install tflite-support

TensorFlowLiteメタデータツールはPython3をサポートしています。

Flatbuffers PythonAPIを使用したメタデータの追加

でモデルのメタデータには3つの部分があり、スキーマは

  1. モデル情報-モデル全体の説明と同様に、このようなライセンス条件などの項目。参照してくださいModelMetadataを
  2. 入力情報-入力の説明および前処理は、正規化などの必要。参照してくださいSubGraphMetadata.input_tensor_metadataを
  3. 出力情報-出力の説明と後処理ような標識へのマッピングとして必要。参照してくださいSubGraphMetadata.output_tensor_metadataを

TensorFlow Liteはこの点だけで、単一の部分グラフをサポートしているため、 TensorFlow LiteのコードジェネレータAndroidのメーカーMLバインド機能が使用されますModelMetadata.nameModelMetadata.description 、代わりのSubGraphMetadata.nameSubGraphMetadata.description 、メタデータを表示し、コード生成を。

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

入力と出力のTensorFlowLiteメタデータは、特定のモデルタイプを念頭に置いて設計されているのではなく、入力と出力のタイプを考慮して設計されています。入力タイプと出力タイプが以下または以下の組み合わせで構成されている限り、モデルが機能的に何をするかは問題ではありません。TensorFlowLiteメタデータでサポートされています。

  • 機能-符号なし整数またはfloat32である数値。
  • 画像-メタデータは現在、RGBおよびグレースケール画像をサポートしています。
  • バウンディングボックス-長方形のバウンディングボックス。スキーマをサポート番号方式の様々な

関連ファイルをパックする

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

関連付けられたファイルは、メタデータPythonライブラリを介してモデルにバンドルできるようになりました。新しいTensorFlowLiteモデルは、モデルと関連ファイルの両方を含むzipファイルになります。一般的なzipツールで解凍できます。この新しいモデル形式は、同じファイル拡張子を使用し続ける.tflite 。既存のTFLiteフレームワークおよびインタープリターと互換性があります。参照モデルにパックのメタデータと関連付けられているファイルの詳細について。

関連するファイル情報をメタデータに記録できます。ファイルタイプ及びファイル(すなわちに取り付けられている場所に応じModelMetadataSubGraphMetadata 、及びTensorMetadata )、 TensorFlowライトアンドロイドコードジェネレータがオブジェクトに自動的にプリ/ポスト処理に対応適用することができます。参照してください。それぞれ関連付けたファイルタイプの<codegenの使用方法>セクションの詳細についてスキーマ内を。

正規化および量子化パラメーター

正規化は、機械学習における一般的なデータ前処理手法です。正規化の目的は、値の範囲の違いを歪めることなく、値を共通のスケールに変更することです。

モデル量子化は、ストレージおよび計算の両方の重みおよび必要に応じて、活性化の低減精度表現を可能にする技術です。

前処理と後処理に関しては、正規化と量子化は2つの独立したステップです。詳細はこちらです。

正規化量子化

それぞれfloatモデルとquantモデルのMobileNetの入力画像のパラメーター値の例。
フロートモデル
-平均:127.5
-標準:127.5
クワントモデル
-平均:127.5
-標準:127.5
フロートモデル
-zeroPoint:0
-スケール:1.0
クワントモデル
-zeroPoint:128.0
-スケール:0.0078125f




いつ呼び出すのですか?


入力:入力データがトレーニングに正規化されている場合は、推論ニーズの入力データに応じて正規化します。
出力:出力データは、一般的に正規化されることはありません。
フロートモデルは、量子化を必要としません。
量子化されたモデルは、または事前/事後処理で量子化を必要としない場合があります。入出力テンソルのデータ型によって異なります。
-フロートテンソル:前処理/後処理での量子化は必要ありません。 QuantopとDequantopがモデルグラフに組み込まれます。
--int8 / uint8テンソル:前処理/後処理で量子化が必要です。


方式


normalized_input =(入力-平均)/ std
入力のクオンタイズ
q = f /スケール+ zeroPoint
出力のために逆量子化
f =(q-zeroPoint)*スケール

パラメータはどこにありますか
モデル作成者によって満たされたとして、モデルのメタデータに保存されているNormalizationOptions TFLiteコンバーターによって自動的に入力され、tfliteモデルファイルに保存されます。
パラメータを取得する方法は? MetadataExtractor API [2] TFLiteスルーTensor API [1]または貫通MetadataExtractor API [2]
floatモデルとquantモデルは同じ値を共有しますか?はい、floatモデルとquantモデルには同じ正規化パラメーターがありますいいえ、フロートモデルは量子化を必要としません。
TFLiteコードジェネレーターまたはAndroidStudio MLバインディングは、データ処理で自動的に生成しますか?
はい

はい

[1] TensorFlow LiteののJava APITensorFlow LiteのC ++ API
[2]メタデータ抽出ライブラリー

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

TensorFlow Liteのタスク・ライブラリーは、あなたが設定している場合、あなたのために正規化を扱うことができるNormalizationOptionsメタデータに。量子化および非量子化処理は常にカプセル化されます。

さまざまなタイプのモデルのメタデータをどのように設定するかについての例は、次のとおりです。

画像分類

スクリプトをダウンロードして、ここにメタデータを移入した、 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()

画像入力

画像は、機械学習の一般的な入力タイプです。 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()

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

メタデータFlatbuffersが作成されると、メタデータとラベルファイルを経由してTFLiteファイルに書き込まれpopulate方法:

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をあなたのメタデータを視覚化するために、またはあなたが使用してJSON形式にTensorFlow Liteのモデルからメタデータを読み取ることができMetadataDisplayer

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のメーカーはまたを通じて、メタデータを表示するサポートのAndroidメーカーMLバインディング機能

メタデータのバージョン管理

メタデータスキーマは、スキーマファイルの変更を追跡し、そして真のバージョンとの互換性を示すFlatbuffersファイル識別によるセマンティックバージョン番号の両方をバージョン管理されています。

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

メタデータスキーマはによってバージョン管理されている意味バージョン番号ようMAJOR.MINOR.PATCHとして、。これは、規則に従って、スキーマの変更を追跡し、ここ。参照フィールドの歴史のバージョンの後に追加1.0.0

Flatbuffersファイルの識別

セマンティックバージョニングは、ルールに従っている場合に互換性を保証しますが、真の非互換性を意味するものではありません。 MAJOR番号を上げる場合、必ずしも下位互換性が失われることを意味するわけではありません。したがって、我々は使用Flatbuffersファイル識別をfile_identifierメタデータスキーマの真の互換性を示すために、。ファイル識別子は正確に4文字の長さです。これは特定のメタデータスキーマに固定されており、ユーザーによる変更の対象にはなりません。メタデータスキーマの下位互換性を何らかの理由で破る必要がある場合、file_identifierは、たとえば「M001」から「M002」にバンプします。 File_identifierは、metadata_versionよりもはるかに少ない頻度で変更されると予想されます。

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

最低限必要なメタデータパーサーバージョンは、完全にメタデータFlatbuffersを読み取ることができるメタデータパーサー(コード生成Flatbuffers)の最小バージョンです。バージョンは、事実上、入力されたすべてのフィールドのバージョンの中で最大のバージョン番号であり、ファイル識別子によって示される互換性のある最小のバージョンです。最低限必要なメタデータパーサーバージョンが自動的によって移入されMetadataPopulatorメタデータがTFLiteモデルに取り込まれたとき。参照してください。メタデータ抽出を最低限必要なメタデータパーサのバージョンが使用されている方法の詳細については。

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

メタデータ抽出ライブラリは、異なるプラットフォーム間でのモデルからのメタデータと関連するファイルを(参照読み込むための便利なツールであるJavaバージョンC ++版)。 Flatbuffersライブラリを使用して、他の言語で独自のメタデータ抽出ツールを構築できます。

Javaでメタデータを読む

あなたのAndroidアプリでメタデータ抽出ライブラリを使用するには、我々が使用することをお勧めTensorFlow LiteのメタデータのAARをMavenCentralでホストされています。それは含まれていMetadataExtractorためにクラスだけでなく、FlatBuffers Javaバインディングをメタデータスキーマモデルスキーマ

あなたは、あなたにこれを指定することができますbuild.gradle次のように依存関係:

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

毎晩のスナップショットを使用するには、あなたが追加したことを確認してSonatypeスナップショットリポジトリを

あなたは、初期化することができMetadataExtractor持つオブジェクトByteBufferモデルを指していること:

public MetadataExtractor(ByteBuffer buffer);

ByteBuffer全体の生涯不変でなければなりませんMetadataExtractorオブジェクト。モデルメタデータのFlatbuffersファイル識別子がメタデータパーサーの識別子と一致しない場合、初期化が失敗する可能性があります。参照してください。メタデータはバージョン管理の詳細については。

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

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インタプリタは、現在唯一の部分グラフをサポートしています。したがって、 MetadataExtractorそのメソッドに入力引数としてサブグラフインデックスを省略しています。

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

メタデータと関連ファイルを含むTensorFlowLiteモデルは、基本的に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;