Google I/O にご注目いただきありがとうございます。すべてのセッションをオンデマンドで表示オンデマンドで見る

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

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

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

メタデータ形式のモデル

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をサポートしています。

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

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

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

TensorFlow Liteは現時点では単一のサブグラフのみをサポートしているため、 TensorFlowLiteコードジェネレーターとAndroidStudio MLバインディング機能は、メタデータを表示してコードを生成するときに、 SubGraphMetadata.name ModelMetadata.description ModelMetadata.name SubGraphMetadata.description使用します。

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

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

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

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

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

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

関連するファイル情報をメタデータに記録できます。ファイルの種類とファイルが添付されている場所( ModelMetadataSubGraphMetadataTensorMetadataなど)に応じて、TensorFlowLiteAndroidコードジェネレーターは対応する前処理/後処理をオブジェクトに自動的に適用する場合があります。詳細については、スキーマ内の各関連ファイルタイプの<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 =(input-mean)/ std
入力の定量化
q =f/スケール+zeroPoint
出力の非量子化
f =(q-zeroPoint)*スケール

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

はい

[1] TensorFlow LiteJavaAPIおよびTensorFlowLiteC++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を使用してメタデータを視覚化するか、 MetadataDisplayerを使用してTensorFlowLiteモデルから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は、 AndroidStudioMLバインディング機能によるメタデータの表示もサポートしています。

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

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

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

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

Flatbuffersファイルの識別

セマンティックバージョニングは、ルールに従っている場合に互換性を保証しますが、真の非互換性を意味するものではありません。 MAJOR番号を上げる場合、必ずしも下位互換性が失われていることを意味するわけではありません。したがって、 FlatbuffersファイルIDfile_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の下位互換性メカニズムにより、メタデータエクストラクタは、一致するファイル識別子を使用して、過去および将来のすべてのスキーマから生成されたメタデータを正常に読み取ります。ただし、将来のスキーマのフィールドは、古いメタデータエクストラクタでは抽出できません。メタデータの最低限必要なパーサーバージョンは、メタデータフラットバッファーを完全に読み取ることができるメタデータパーサーの最小バージョンを示します。次の方法を使用して、必要最小限のパーサーバージョン条件が満たされているかどうかを確認できます。

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 :を使用して実行できます。

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