Google I / Oの基調講演、製品セッション、ワークショップなどを見るプレイリストを見る

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

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

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

メタデータ形式のモデル

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

モデルメタデータは、 FlatBufferファイルであるmetadata_schema.fbsで定義されています。図1に示すように、 TFLiteモデルスキーマのメタデータフィールドに"TFLITE_METADATA"という名前で格納されます。一部のモデルには、 分類ラベルファイルなどの関連ファイルが付属している場合があります。これらのファイルは、ZipFileの「追加」モード'a'モード)を使用して、元のモデルファイルの末尾にZIPとして連結されます。 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フレームワークおよびインタープリターと互換性があります。詳細については、 mtadataおよび関連ファイルをモデルにパックするを参照してください。

関連するファイル情報をメタデータに記録できます。ファイルの種類とファイルの添付先( ModelMetadataSubGraphMetadataTensorMetadata )に応じて、TensorFlow LiteAndroidコードジェネレーターは対応する前処理/後処理をオブジェクトに自動的に適用する場合があります。詳細について、スキーマ内の各関連ファイルタイプの<Codegenusage>セクションを参照してください。

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

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

モデルの量子化は、重みの精度の低い表現と、オプションで、ストレージと計算の両方のアクティブ化を可能にする手法です。

前処理と後処理に関しては、正規化と量子化は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介して[2] TFLite Tensor API [1]またはMetadataExtractor [2]を介して
floatモデルとquantモデルは同じ値を共有しますか?はい、floatモデルとquantモデルには同じ正規化パラメーターがありますいいえ、フロートモデルは量子化を必要としません。
TFLiteコードジェネレーターまたはAndroidStudio MLバインディングは、データ処理で自動的に生成しますか?
はい

はい

[1] TensorFlow Lite JavaAPIおよびTensorFlowLite C ++ API
[2]メタデータ抽出ライブラリ

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

メタデータでNormalizationOptionsを設定すると、 TensorFlowLiteタスクライブラリで正規化を処理できます。量子化および非量子化処理は常にカプセル化されます。

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

画像分類

ここからスクリプトをダウンロードします。 このスクリプト、メタデータを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()

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

メタデータフラットバッファが作成されると、メタデータとラベルファイルが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をあなたのメタデータを視覚化するために、またはあなたが使用して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 Studioは、 Android StudioMLバインディング機能によるメタデータの表示もサポートしています

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

メタデータスキーマは、スキーマファイルの変更を追跡するSemanticバージョン番号と、実際のバージョンの互換性を示すFlatbuffersファイルIDの両方によってバージョン管理されます。

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

メタデータスキーマは、MAJOR.MINOR.PATCHなどのセマンティックバージョン番号によってバージョン管理されます。 ここのルールに従ってスキーマの変更を追跡します。バージョン1.0.0以降に追加されたフィールド履歴を参照してください。

Flatbuffersファイルの識別

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

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

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

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

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

Javaでメタデータを読む

AndroidアプリでMetadataExtractorライブラリを使用するには、 MavenCentralでホストされているTensorFlowLiteメタデータAARを使用することをお勧めします。これには、 MetadataExtractorクラスと、 メタデータスキーマおよびモデルスキーマのFlatBuffersJavaバインディングが含まれています

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

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

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

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

public MetadataExtractor(ByteBuffer buffer);

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

Flatbuffersの下位互換性メカニズムにより、一致するファイル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は、メソッドの入力引数としてサブグラフインデックスを省略します。

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

メタデータと関連ファイルを含む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 :をModelMetadataExtractor::GetAssociatedFileして実行できます。

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