TF1.x から TF2 への移行の概要

TensorFlow 2 は、いくつかの点で TF1.x とは根本的に異なります。次のようにすると、未変更の TF1.x コード(contrib を除く)を TF2 バイナリインストールで引き続き実行できます。

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

ただし、これは TF2 の動作と API を実行していないため、TF2 用に記述されたコードでは期待どおりに動作しない可能性があります。TF2 の動作をアクティブにして実行していない場合は、TF2 インストールの上で TF1.x を実行していることになります。TF2 と TF1.x の違いの詳細については、TF1 と TF2 の動作ガイドを参照してください。

このガイドでは、TF1.x コードを TF2 に移行するプロセスの概要を説明します。これにより、新機能および今後の機能改善を利用できるようになります。また、コードがよりシンプルになり、パフォーマンスが向上し、メンテナンスが容易になります。

tf.keras の高レベル API を使用し、model.fit のみでトレーニングしている場合、コードは次の場合を除いて、TF2 とほぼ完全に互換性があるはずです。

TF2 移行プロセス

移行する前に、ガイドを読んで、TF1.x と TF2 の動作と API の違いについて学習してください。

  1. 自動スクリプトを実行して、TF1.x API の使用の一部を tf.compat.v1 に変換します。
  2. 古い tf.contrib シンボルを削除します(TF AddonsTF-Slim を確認してください)。
  3. Eager execution を有効にして、TF1.x モデルのフォワードパスを TF2 で実行します。
  4. トレーニングループとモデルの保存/読み込み用の TF1.x コードを TF2 の同等のものにアップグレードします。
  5. (オプション)TF2 互換の tf.compat.v1 API を慣用的な TF2 API に移行します。

次のセクションでは、上記の手順を詳しく説明します。

シンボル変換スクリプトを実行する

これは、TF 2.x バイナリに対して実行するようにコードシンボルを書き換える際に初期パスを実行しますが、これによりコードが TF 2.x に対して慣用的になったり、自動的にコードが TF2 の動作と互換性を持つことはありません。

多くの場合、コードは、プレースホルダー、セッション、コレクション、およびその他の TF1.x スタイルの機能にアクセスするために、tf.compat.v1 エンドポイントを引き続き使用します。

シンボル変換スクリプトを使用するためのベストプラクティスの詳細については、ガイドを参照してください。

tf.contrib の使用を削除

tf.contrib モジュールは廃止され、そのサブモジュールのいくつかが Core TF2 API に統合されました。他のサブモジュールは、TF IOTF Addons などの他のプロジェクトにスピンオフされました。

古い TF1.x コードの多くは、tf.contrib.layers として TF1.x にパッケージ化された Slim ライブラリを使用しています。Slim コードを TF2 に移行する場合は、使用する Slim API が tf-slim pip パッケージを指すように切り替えます。その後、モデルマッピングガイドを読み、Slim コードを変換する方法を学びます。

Slim 事前トレーニング済みモデルを使用する場合は、tf.keras.applications から Keras 事前トレーニング済みモデル、または元の Slim コードからエクスポートされた TF Hub の TensorFlow 2 SavedModel をお試しください。

TF2 動作を有効にして TF1.x モデルのフォワードパスを実行する

変数と損失を追跡する

TF2 はグローバルコレクションをサポートしていません。

TF2 の Eager execution は、tf.Graph コレクションベースの API をサポートしていません。これは、変数の作成方法と追跡方法に影響します。

新しい TF2 コードでは、v1.get_variable の代わりに tf.Variable を使用し、tf.compat.v1.variable_scope の代わりに Python オブジェクトを使用して変数を収集および追跡します。通常、これは次のいずれかになります。

tf.Graph.get_collection(tf.GraphKeys.VARIABLES) などの変数のリストを集める必要がある場合には、LayerModule、および Model オブジェクトの .variables.trainable_variables 属性を使用します。

これら LayerModel クラスは、グローバルコレクションの必要性を除去した別のプロパティを幾つか実装します。.losses プロパティは、tf.GraphKeys.LOSSES コレクション使用の置き換えとなります。

TF2 コードモデリング shim を使用して既存の get_variable および variable_scope ベースのコードを LayersModels、および Modules 内に埋め込む方法の詳細については、モデルマッピングガイドを参照してください。これにより、大幅な書き換えを行うことなく、Eager execution を有効にしてフォワードパスを実行できます。

他の動作の変更への適応

モデルフォワードパスを実行して他の動作変更を実行するのにモデルマッピングガイドだけでは不十分な場合は、TF1.x と TF2 の動作の比較に関するガイドを参照してください。他の動作の変更と、それらに適応する方法について学べます。詳細については、サブクラス化ガイドによる新しいレイヤーとモデルの作成も参照してください。

結果の検証

イーガー実行が有効な場合にモデルが正しく動作していることを (数値的に)検証する方法に関する簡単なツールとガイダンスについては、モデル検証ガイドを参照してください。モデルマッピングガイドと合わせて参照することをお勧めします。

トレーニング、評価、インポート/エクスポートコードのアップグレード

v1.Session スタイルの tf.estimator.Estimator およびその他のコレクションベースのアプローチで構築された TF1.x トレーニングループは、TF2 の新しい動作と互換性がありません。TF2 コードと組み合わせると予期しない動作が発生する可能性があるため、すべての TF1.x トレーニングコードを移行することが重要です。

これを行うには、いくつかの方法から選択できます。

最高レベルのアプローチは、tf.keras を使用することです。Keras の高レベル関数は、独自のトレーニングループを記述する場合に見逃しやすい多くの低レベルの詳細を管理します。たとえば、それらは自動的に正規化損失を収集し、モデルを呼び出すときに training=True 引数を設定します。

tf.estimator.Estimator のコードを移行してバニラおよびカスタム tf.keras トレーニングループを使用する方法については Estimator 移行ガイドを参照してください。

カスタムトレーニングループを使用すると、個々のレイヤーの重みを追跡するなど、モデルをより細かく制御できます。tf.GradientTape を使用してモデルの重みを取得し、それらを使用してモデルを更新する方法については、ゼロからトレーニングループを構築するガイドを参照してください。

TF1.x オプティマイザを Keras オプティマイザに変換する

Adam オプティマイザ勾配降下オプティマイザなどの tf.compat.v1.train 内のオプティマイザには、tf.keras.optimizers 内に同等のものをもちます。

以下の表は、これらのレガシーオプティマイザを Keras の同等のものに変換する方法をまとめたものです。追加の手順(デフォルトの学習率の更新など)が必要でない限り、TF1.x バージョンを TF2 バージョンに直接置き換えることができます。

オプティマイザをアップグレードすると、古いチェックポイントに互換性がなくなる可能性があるので注意してください。

TF1.x TF2 追加の手順
`tf.v1.train.GradientDescentOptimizer` tf.keras.optimizers.SGD なし
`tf.v1.train.MomentumOptimizer` tf.keras.optimizers.SGD `momentum` 引数を含める
`tf.v1.train.AdamOptimizer` tf.keras.optimizers.Adam `beta1` および `beta2` 引数の名前を `beta_1` および `beta_2` に変更する
`tf.v1.train.RMSPropOptimizer` tf.keras.optimizers.RMSprop `decay` 引数の名前を `rho` に変更する
`tf.v1.train.AdadeltaOptimizer` tf.keras.optimizers.Adadelta なし
`tf.v1.train.AdagradOptimizer` tf.keras.optimizers.Adagrad なし
`tf.v1.train.FtrlOptimizer` tf.keras.optimizers.Ftrl `accum_name` および `linear_name` 引数を削除する
`tf.contrib.AdamaxOptimizer` tf.keras.optimizers.Adamax `beta1` および `beta2` 引数の名前を `beta_1` および `beta_2` に変更する
`tf.contrib.Nadam` tf.keras.optimizers.Nadam `beta1` および `beta2` 引数の名前を `beta_1` および `beta_2` に変更する

注意: TF2 では、すべてのイプシロン(数値安定定数)のデフォルトが 1e-8 ではなく 1e-7 になりました。ほとんどの場合、この違いは無視できます。

データ入力パイプラインをアップグレードする

データをtf.kerasモデルに供給するには多くの方法があります。それらは入力として Python ジェネレータと Numpy 配列を受け取ります。

モデルへのデータ供給方法として推奨しているのは、データ操作用の高パフォーマンスなクラスのコレクションを含んだ tf.data パッケージの使用です。tf.data に属する dataset は効率的で表現力があり、TF2 と統合できます。

次のように、tf.keras.Model.fit メソッドに直接渡すことができます。

model.fit(dataset, epochs=5)

また、標準的な Python で直接イテレートすることもできます。

for example_batch, label_batch in dataset:
    break

依然としてtf.queueを使用している場合、これらは入力パイプラインとしてではなく、データ構造としてのみ対応されます。

tf.feature_columns を使用する特徴前処理コードもすべて移行する必要があります。詳細については、移行ガイドを参照してください。

モデルの保存と読み込み

TF2 は、オブジェクトベースのチェックポイントを使用します。名前ベースの TF1.x チェックポイントからの移行についての詳細は、チェックポイント移行ガイドを参照してください。TensorFlow Core ドキュメントのチェックポイントガイドも参照してください。

保存されたモデルには、重大な互換性の問題はありません。TF1.x の SavedModel を TF2 に移行する方法についての詳細は、SavedModel ガイドを参照してください。一般に、

  • TF1.x の saved_models は TF2 で機能します。
  • すべての ops がサポートされている場合、TF2 saved_models は TF1.x で機能します。

Graph.pb および Graph.pbtxt オブジェクトの操作の詳細については、SavedModel 移行ガイドの GraphDef セクションも参照してください。

(オプション)tf.compat.v1 シンボルを移行する

tf.compat.v1 モジュールには、元のセマンティクスを持つ完全な TF1.x API が含まれています。

上記の手順に従って、すべての TF2 動作と完全に互換性のあるコードになった後でも、TF2 と互換性のある compat.v1 API について多くの言及がある可能性があります。これらの従来の compat.v1 API は、作成済みのコードに対して引き続き機能しますが、新しくコードを作成する場合は使用しないでください。

ただし、既存の使用法を非レガシー TF2 API に移行することがあるかもしれません。多くの場合、個々の compat.v1 シンボルのドキュメント文字列は、それらを非レガシー TF2 API に移行する方法を説明しています。また、慣用的な TF2 API への増分移行に関するモデルマッピングガイドのセクションも参照してください。

リソースとその他の文献

前述のとおり、すべての TF1.x コードを TF2 に移行することを推薦します。詳細については、TensorFlow ガイドの TF2 の移行セクションを参照してください。