再利用可能なSavedModels

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

序章

TensorFlow Hub は、TensorFlow 2 の SavedModel などのアセットをホストします。これらは、 obj = hub.load(url) [詳細] を使用して Python プログラムに再度読み込むことができます。返されるobjtf.saved_model.load()の結果です (TensorFlow のSavedModel ガイドを参照してください)。このオブジェクトは、tf.functions、tf.Variables (事前にトレーニングされた値から初期化された)、その他のリソース、および再帰的にそのようなオブジェクトである任意の属性を持つことができます。

このページでは、TensorFlow Python プログラムで再利用するために、読み込まれたobjによって実装されるインターフェイスについて説明します。このインターフェースに準拠する SavedModel は、再利用可能な SavedModelと呼ばれます。

再利用とは、微調整する機能を含め、 objを中心に大きなモデルを構築することを意味します。微調整とは、周囲のモデルの一部としてロードされたobjの重みをさらにトレーニングすることを意味します。損失関数とオプティマイザーは、周囲のモデルによって決定されます。 objは、ドロップアウトやバッチ正規化などの手法を含む可能性のある、入力から出力へのアクティベーション (「フォワード パス」) のマッピングのみを定義します。

TensorFlow Hub チームは、上記の意味で再利用されるすべての SavedModel に Reusable SavedModel インターフェースを実装することを推奨しています。 tensorflow_hubライブラリの多くのユーティリティ、特にhub.KerasLayerでは、それを実装するために SavedModels が必要です。

SignatureDefs との関係

tf.functions およびその他の TF2 機能に関するこのインターフェイスは、TF1 から利用可能であり、推論のために TF2 で引き続き使用されている SavedModel の署名とは別のものです (SavedModels を TF Serving または TF Lite にデプロイするなど)。推論のための署名は、微調整をサポートするほど十分に表現力がありませんtf.functionは、再利用されたモデルに対してより自然で表現力豊かなPython APIを提供します。

モデル構築ライブラリとの関係

Reusable SavedModel は、Keras や Sonnet などの特定のモデル構築ライブラリとは無関係に、TensorFlow 2 プリミティブのみを使用します。これにより、モデル構築ライブラリ全体での再利用が容易になり、元のモデル構築コードへの依存がなくなります。

Reusable SavedModels を特定のモデル構築ライブラリにロードしたり、そこから保存したりするには、ある程度の適応が必要になります。 Keras の場合、 hub.KerasLayerが読み込みを提供し、Keras の SavedModel 形式での組み込みの保存は、このインターフェイスのスーパーセットを提供する目的で TF2 用に再設計されました (2019 年 5 月のRFCを参照)。

タスク固有の「共通の SavedModel API」との関連

このページのインターフェイス定義では、任意の数とタイプの入力と出力が可能です。 TF Hub の Common SavedModel API は、この一般的なインターフェイスを特定のタスクの使用規則で改良して、モデルを簡単に交換できるようにします。

インターフェース定義

属性

Reusable SavedModel は、 obj = tf.saved_model.load(...)が次の属性を持つオブジェクトを返すような TensorFlow 2 SavedModel です。

  • __call__ .必須。以下の仕様に従うモデルの計算 (「フォワード パス」) を実装する tf.function。

  • variables : tf.Variable オブジェクトのリスト。トレーニング可能なものとトレーニング不可能なものの両方を含む、 __call__の可能な呼び出しによって使用されるすべての変数をリストします。

    このリストは、空の場合は省略できます。

  • trainable_variables : v.trainable がすべての要素に対して true であるようなv.trainableオブジェクトのリスト。これらの変数は、 variablesのサブセットである必要があります。これらは、オブジェクトを微調整するときにトレーニングする変数です。 SavedModel の作成者は、微調整中に変更してはならないことを示すために、元々訓練可能だったいくつかの変数をここで省略することを選択する場合があります。

    特に、SavedModel が微調整をサポートしていない場合は、空の場合、このリストを省略できます。

  • regularization_losses : tf.functions のリスト。それぞれがゼロ入力を取り、単一のスカラー浮動小数点テンソルを返します。微調整のために、SavedModel ユーザーはこれらを追加の正則化項として損失に含めることをお勧めします (最も単純なケースでは、それ以上のスケーリングはありません)。通常、これらは重みの正則化を表すために使用されます。 (入力がないため、これらの tf.functions はアクティビティ正規化子を表現できません。)

    特に、SavedModel が微調整をサポートしていないか、重みの正則化を規定したくない場合は、空の場合、このリストを省略できます。

__call__関数

Restored SavedModel objには、復元された tf.function であるobj.__call__属性があり、次のようにobjを呼び出すことができます。

概要 (疑似コード):

outputs = obj(inputs, trainable=..., **kwargs)

引数

引数は次のとおりです。

  • SavedModel の入力アクティベーションのバッチには、位置指定の必須引数が 1 つあります。そのタイプは次のいずれかです。

    • 単一の入力に対する単一の Tensor、
    • 名前のない入力の順序付けられたシーケンスのテンソルのリスト、
    • 入力名の特定のセットによってキー付けされた Tensor の辞書。

    (このインターフェースの将来のリビジョンでは、より一般的なネストが許可される可能性があります。) SavedModel の作成者は、それらの 1 つと、テンソルの形状と dtype を選択します。必要に応じて、形状の一部の寸法を未定義にする必要があります (特にバッチ サイズ)。

  • Python ブール値のTrueまたはFalseを受け入れるオプションのキーワード引数trainingがある場合があります。デフォルトはFalseです。モデルが微調整をサポートし、その計算が 2 つの間で異なる場合 (ドロップアウトとバッチ正規化など)、その区別はこの引数で実装されます。それ以外の場合、この引数は存在しない可能性があります。

    __call__が Tensor 値のtraining引数を受け入れる必要はありません。それらの間でディスパッチする必要がある場合は、呼び出し元がtf.cond()を使用する必要があります。

  • SavedModel 作成者は、特定の名前のより多くのオプションのkwargsを受け入れることを選択できます。

    • Tensor 値の引数については、SavedModel の作成者が許容される dtype と形状を定義します。 tf.functionは、tf.TensorSpec 入力でトレースされる引数で Python デフォルト値を受け入れます。このような引数を使用して、 __call__に含まれる数値ハイパーパラメーター (ドロップアウト率など) をカスタマイズできます。

    • Python 値の引数については、SavedModel 作成者が許容値を定義します。このような引数は、トレースされる関数で個別の選択を行うためのフラグとして使用できます (ただし、トレースの組み合わせ爆発に注意してください)。

復元された__call__関数は、許容されるすべての引数の組み合わせのトレースを提供する必要があります。 TrueFalseの間でtrainingを反転させても、引数の許容性が変わってはなりません。

結果

objの呼び出しからのoutputsは次のようになります。

  • 単一の出力に対する単一の Tensor、
  • 名前のない出力の順序付けられたシーケンスのテンソルのリスト、
  • 出力名の特定のセットによってキー付けされた Tensor の辞書。

(このインターフェイスの将来のリビジョンでは、より一般的なネストが許可される可能性があります。) 戻り値の型は、Python 値の kwargs によって異なる場合があります。これにより、追加の出力を生成するフラグが可能になります。 SavedModel 作成者は、出力の dtype と shape および入力への依存性を定義します。

名前付き callable

再利用可能な SavedModel は、上記の方法で複数のモデル ピースを提供できます。たとえば、それらをobj.fooobj.barなどの名前付きサブオブジェクトに配置します。各サブオブジェクトは、 __call__メソッドと、そのモデル部分に固有の変数などに関するサポート属性を提供します。上記の例では、 obj.foo.__call__obj.foo.variablesなどがあります。

このインターフェースは、裸の tf.function をtf.fooとして直接追加するアプローチをカバーしていないことに注意してください。

再利用可能な SavedModel のユーザーは、1 レベルのネスト ( obj.barであり、 obj.bar.bazではありません) のみを処理することが期待されています。 (このインターフェースの将来のリビジョンでは、より深いネストが許可される可能性があり、最上位オブジェクト自体が呼び出し可能であるという要件が放棄される可能性があります。)

閉会の辞

インプロセス API との関係

このドキュメントは、 tf.saved_model.save()およびtf.saved_model.load() ) によるシリアライゼーションによるラウンドトリップを生き残る tf.function および tf.Variable のようなプリミティブで構成される Python クラスのインターフェースについて説明します。ただし、インターフェースはtf.saved_model.save()に渡された元のオブジェクトに既に存在していました。そのインターフェースへの適応により、単一の TensorFlow プログラム内のモデル構築 API 間でモデル ピースの交換が可能になります。