web-dev-qa-db-ja.com

Tensorflowのバッチ標準の保存/復元

Tensorflowでバッチノルムを使用してモデルをトレーニングしました。モデルを保存して、さらに使用できるように復元したいと思います。バッチノルムはによって行われます

def batch_norm(input, phase):
    return tf.layers.batch_normalization(input, training=phase)

ここで、フェーズはトレーニング中はTrue、テスト中はFalseです。

単に電話するようです

saver = tf.train.Saver()
saver.save(sess, savedir + "ckpt")

モデルを復元すると、最初は正常に復元されたと表示されるため、うまく機能しません。また、Attempting to use uninitialized value batch_normalization_585/betaグラフで1つのノードを実行した場合。これは、モデルを適切に保存しないこと、または私が見逃した他の何かに関連していますか?

7
ALeex

また、「初期化されていない値batch_normalization_585/betaを使用しようとしています」というエラーが発生しました。これは、次のように空の角かっこでセーバーを宣言することによって発生します。

         saver = tf.train.Saver() 

セーバーは、バッチ正規化の移動平均を含まないtf.trainable_variables()に含まれる変数を保存します。この変数を保存されたckptに含めるには、次のことを行う必要があります。

         saver = tf.train.Saver(tf.global_variables())

これはすべての変数を保存するので、非常にメモリを消費します。または、移動する平均または分散を持つ変数を識別し、次のように宣言して保存する必要があります。

         saver = tf.train.Saver(tf.trainable_variables() + list_of_extra_variables)
8
simo23

これを説明する必要があるかどうかはわかりませんが、念のため(および他の潜在的な視聴者のために)。

TensorFlowで操作を作成するたびに、新しいノードがグラフに追加されます。グラフ内の2つのノードに同じ名前を付けることはできません。作成する任意のノードの名前を定義できますが、名前を指定しない場合、TensorFlowは決定論的な方法でノードを選択します(つまり、ランダムではなく、常に同じシーケンスで)。 2つの数値を加算すると、おそらくAddになりますが、別の加算を行うと、2つのノードに同じ名前を付けることはできないため、Add_2のようになります。グラフにノードが作成されると、その名前は変更できません。多くの関数は、いくつかのサブノードを順番に作成します。たとえば、tf.layers.batch_normalizationはいくつかの内部変数betagammaを作成します。

保存と復元は次のように機能します。

  1. 必要なモデルを表すグラフを作成します。このグラフには、セーバーによって保存される変数が含まれています。
  2. そのグラフを使用して、初期化、トレーニング、または必要な操作を行うと、モデル内の変数にいくつかの値が割り当てられます。
  3. セーバーでsaveを呼び出して、変数の値をファイルに保存します。
  4. ここで、モデルを別のグラフに再作成します(別のPythonセッション全体にすることも、別のグラフを共存させることもできます)モデルは、最初のモデルとまったく同じ方法で作成する必要があります。
  5. セーバーでrestoreを呼び出して、変数の値を取得します。

これが機能するためには、最初と2番目のグラフの変数の名前がまったく同じである必要があります。

あなたの例では、TensorFlowは変数batch_normalization_585/betaについて文句を言っています。同じグラフでtf.layers.batch_normalizationを600回近く呼び出したようです。そのため、多くのbeta変数がぶら下がっています。実際にこれだけの数が必要かどうかは疑わしいので、APIを試しているだけで、最終的にはその数のコピーが作成されたと思います。

これが機能するはずのドラフトです:

import tensorflow as tf

def make_model():
    input = tf.placeholder(...)
    phase = tf.placeholder(...)
    input_norm = tf.layers.batch_normalization(input, training=phase))
    # Do some operations with input_norm
    output = ...
    saver = tf.train.Saver()
    return input, output, phase, saver

# We work with one graph first
g1 = tf.Graph()
with g1.as_default():
    input, output, phase, saver = make_model()
    with tf.Session() as sess:
        # Do your training or whatever...
        saver.save(sess, savedir + "ckpt")

# We work with a second different graph now
g2 = tf.Graph()
with g2.as_default():
    input, output, phase, saver = make_model()
    with tf.Session() as sess:
        saver.restore(sess, savedir + "ckpt")
        # Continue using your model...

繰り返しますが、典型的なケースは、2つのグラフを並べるのではなく、1つのグラフを作成し、後で別のPythonセッションで再作成しますが、最終的には両方とも同じです。重要な部分は、どちらの場合もモデルが同じ方法で(したがって、同じノード名で)作成されることです。

4
jdehesa