前書き
TensorFlow Hubは、他のアセットの中でも特にTensorFlow2のSavedModelsをホストします。それらは、 obj = hub.load(url)
[詳細]を使用してPythonプログラムにロードして戻すことができます。返されるobj
は、 tf.saved_model.load()
結果です(TensorFlowのSavedModelガイドを参照)。このオブジェクトは、tf.functions、tf.Variables(事前にトレーニングされた値から初期化される)、その他のリソース、および再帰的に、より多くのそのようなオブジェクトである任意の属性を持つことができます。
このページでは、TensorFlow Pythonプログラムで再利用するために、ロードされたobj
によって実装されるインターフェースについて説明します。このインターフェースに準拠するSavedModelsは、再利用可能なSavedModelsと呼ばれます。
再利用とは、オブジェクトを微調整する機能を含め、 obj
周りに大きなモデルを構築することを意味します。微調整とは、周囲のモデルの一部として、ロードされたobj
重みをさらにトレーニングすることを意味します。損失関数とオプティマイザーは、周囲のモデルによって決定されます。 obj
は、入力から出力のアクティブ化へのマッピング(「フォワードパス」)のみを定義します。これには、ドロップアウトやバッチ正規化などの手法が含まれる場合があります。
TensorFlow Hubチームは、上記の意味で再利用することを目的としたすべてのSavedModelに再利用可能なSavedModelインターフェイスを実装することをお勧めします。 tensorflow_hub
ライブラリの多くのユーティリティ、特にhub.KerasLayer
は、それを実装するためにSavedModelsを必要とします。
SignatureDefsとの関係
tf.functionsおよびその他のTF2機能に関するこのインターフェイスは、TF1以降で使用可能であり、推論のためにTF2で引き続き使用されるSavedModelの署名とは別のものです(SavedModelをTFServingまたはTFLiteにデプロイするなど)。推論のための署名はサポート微調整への表現力は十分ではない、とtf.function
より自然で表現力豊かな提供のPython APIを再利用したモデルのために。
モデル構築ライブラリとの関係
再利用可能なSavedModelは、KerasやSonnetなどの特定のモデル構築ライブラリとは関係なく、TensorFlow2プリミティブのみを使用します。これにより、元のモデル構築コードに依存することなく、モデル構築ライブラリ間での再利用が容易になります。
Reusable SavedModelsを任意のモデル構築ライブラリにロードしたり、そこから保存したりするには、ある程度の適応が必要になります。 Kerasの場合、 hub.KerasLayerが読み込みを提供し、このインターフェイスのスーパーセットを提供することを目的として、SavedModel形式でのKerasの組み込み保存がTF2用に再設計されました(2019年5月のRFCを参照)。
タスク固有の「一般的なSavedModelAPI」との関係
このページのインターフェース定義では、任意の数とタイプの入力と出力が可能です。 TFHubのCommonSavedModel APIは、特定のタスクの使用規則を使用してこの一般的なインターフェイスを改良し、モデルを簡単に交換できるようにします。
インターフェース定義
属性
再利用可能なSavedModelは、 obj = tf.saved_model.load(...)
が次の属性を持つオブジェクトを返すようなobj = tf.saved_model.load(...)
です。
__call__
。必須。以下の仕様に従って、モデルの計算(「フォワードパス」)を実装するtf.function。variables
:tf.Variableのリストは、のいずれかの可能性のある呼び出しによって使用されるすべての変数リスト、オブジェクト__call__
トレーニング可能と非トレーニング可能なものの両方を含むが、。空の場合、このリストは省略できます。
trainable_variables
:tf.Variableのリストがあるようオブジェクトv.trainable
すべての要素についても同様です。これらの変数は、variables
サブセットである必要があり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つの位置的な必須の引数があります。そのタイプは
- 単一の入力に対する単一のテンソル、
- 名前のない入力の順序付けられたシーケンスのテンソルのリスト、
- 入力名の特定のセットによってキー設定されたテンソルの辞書。
(このインターフェースの将来の改訂により、より一般的なネストが可能になる可能性があります。)SavedModel作成者は、それらの1つと、テンソルの形状およびdtypeを選択します。有用な場合は、形状の一部の寸法を未定義にする必要があります(特にバッチサイズ)。
Pythonブール値
True
またはFalse
を受け入れるオプションのキーワード引数training
がある場合があります。デフォルトはFalse
です。モデルが微調整をサポートしていて、その計算が2つの間で異なる場合(たとえば、ドロップアウトとバッチ正規化の場合など)、その区別はこの引数で実装されます。そうでなければ、この議論は存在しないかもしれません。__call__
がテンソル値のtraining
引数を受け入れる必要はありません。呼び出し元は、必要に応じてtf.cond()
を使用してそれらの間でディスパッチする必要があります。SavedModelの作成者は、特定の名前のオプションの
kwargs
を受け入れることを選択できます。テンソル値の引数の場合、SavedModel作成者は許容されるdtypeと形状を定義します。
tf.function
は、tf.TensorSpec入力でトレースされる引数でPythonのデフォルト値を受け入れます。このような引数を使用して、__call__
関連する数値ハイパーパラメータ(ドロップアウト率など)をカスタマイズできます。Python値の引数の場合、SavedModel作成者はそれらの許容値を定義します。このような引数は、トレースされた関数で離散選択を行うためのフラグとして使用できます(ただし、トレースの組み合わせ爆発に注意してください)。
復元された__call__
関数は、許可されているすべての引数の組み合わせのトレースを提供する必要があります。 True
とFalse
間でtraining
を反転させても、引数の許容範囲を変更してはなりません。
結果
obj
呼び出しからのoutputs
は次のようになります。
- 単一の出力に対する単一のテンソル、
- 名前のない出力の順序付けられたシーケンスのテンソルのリスト、
- 特定の出力名のセットによってキー設定されたテンソルの辞書。
(このインターフェースの将来の改訂により、より一般的なネストが可能になる可能性があります。)戻り値の型は、Python値のkwargsによって異なる場合があります。これにより、フラグが追加の出力を生成できるようになります。 SavedModelクリエーターは、出力dtypeと形状、およびそれらの入力への依存関係を定義します。
名前付き呼び出し可能
再利用可能なSavedModelは、 obj.foo
、 obj.bar
などの名前付きサブオブジェクトにそれらを配置することにより、上記の方法で複数のモデルピースを提供できます。各サブオブジェクトは、 __call__
メソッドと、そのモデルピースに固有の変数などに関するサポート属性を提供します。上記の例では、 obj.foo.__call__
、 obj.foo.variables
などがあります。
このインタフェースは、として直接裸tf.functionを添加するアプローチカバーしていないことに注意tf.foo
。
Reusable SavedModelsのユーザーは、1レベルのネストのみを処理することが期待されています( obj.bar
は処理しますが、obj.bar.bazは処理しませobj.bar.baz
)。 (このインターフェースの将来の改訂により、より深いネストが可能になる可能性があり、最上位オブジェクト自体を呼び出すことができるという要件が放棄される可能性があります。)
閉会の辞
インプロセスAPIとの関係
このドキュメントでは、 tf.saved_model.save()
およびtf.saved_model.load()
介したtf.saved_model.save()
によるラウンドトリップに耐えるtf.functionやtf.Variableなどのプリミティブで構成されるPythonクラスのインターフェイスについて説明します。ただし、インターフェイスは、 tf.saved_model.save()
に渡された元のオブジェクトにすでに存在していました。そのインターフェースへの適応により、単一のTensorFlowプログラム内でモデル構築API間でモデルピースを交換できます。