5

私はTensorFlowを使用してニューラルネットワークをトレーニングするためにバッチ正規化を使用しようとしていましたが、the official layer implementation of Batch Normalizationの使用方法はわかりませんでした(これはAPIのものとは異なります)。TensorFlowで公式バッチ正規化レイヤを使用するにはどうすればよいですか?

github issuesで苦労して掘り下げた後、正しく使用するにはtf.condが必要で、BNシフトとスケール変数が適切に再利用されるように 'resue = True'フラグが必要なようです。それを理解した後、私はそれを使用する正しい方法であると信じている方法の小さな説明を提供しましたhere

私はそれをテストするための短いスクリプトを書いています(単一のレイヤーとReLu、これより小さくするのは難しいです)。しかし、私はそれをテストする方法を100%確信していません。現在、私のコードはエラーメッセージなしで実行されますが、予期せずNaNsを返します。これは、私が他の投稿で与えたコードが正しいかもしれないという私の自信を低下させます。または、私が持っているネットワークが変わっているかもしれません。いずれにせよ、誰かが間違っていることを知っていますか?ここでは、コードは次のとおりです。

import tensorflow as tf 
# download and install the MNIST data automatically 
from tensorflow.examples.tutorials.mnist import input_data 
from tensorflow.contrib.layers.python.layers import batch_norm as batch_norm 

def batch_norm_layer(x,train_phase,scope_bn): 
    bn_train = batch_norm(x, decay=0.999, center=True, scale=True, 
    is_training=True, 
    reuse=None, # is this right? 
    trainable=True, 
    scope=scope_bn) 

    bn_inference = batch_norm(x, decay=0.999, center=True, scale=True, 
    is_training=False, 
    reuse=True, # is this right? 
    trainable=True, 
    scope=scope_bn) 

    z = tf.cond(train_phase, lambda: bn_train, lambda: bn_inference) 
    return z 

def get_NN_layer(x, input_dim, output_dim, scope, train_phase): 
    with tf.name_scope(scope+'vars'): 
     W = tf.Variable(tf.truncated_normal(shape=[input_dim, output_dim], mean=0.0, stddev=0.1)) 
     b = tf.Variable(tf.constant(0.1, shape=[output_dim])) 
    with tf.name_scope(scope+'Z'): 
     z = tf.matmul(x,W) + b 
    with tf.name_scope(scope+'BN'): 
     if train_phase is not None: 
      z = batch_norm_layer(z,train_phase,scope+'BN_unit') 
    with tf.name_scope(scope+'A'): 
     a = tf.nn.relu(z) # (M x D1) = (M x D) * (D x D1) 
    return a 

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) 
# placeholder for data 
x = tf.placeholder(tf.float32, [None, 784]) 
# placeholder that turns BN during training or off during inference 
train_phase = tf.placeholder(tf.bool, name='phase_train') 
# variables for parameters 
hiden_units = 25 
layer1 = get_NN_layer(x, input_dim=784, output_dim=hiden_units, scope='layer1', train_phase=train_phase) 
# create model 
W_final = tf.Variable(tf.truncated_normal(shape=[hiden_units, 10], mean=0.0, stddev=0.1)) 
b_final = tf.Variable(tf.constant(0.1, shape=[10])) 
y = tf.nn.softmax(tf.matmul(layer1, W_final) + b_final) 

### training 
y_ = tf.placeholder(tf.float32, [None, 10]) 
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) 
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) 
with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    steps = 3000 
    for iter_step in xrange(steps): 
     #feed_dict_batch = get_batch_feed(X_train, Y_train, M, phase_train) 
     batch_xs, batch_ys = mnist.train.next_batch(100) 
     # Collect model statistics 
     if iter_step%1000 == 0: 
      batch_xstrain, batch_xstrain = batch_xs, batch_ys #simualtes train data 
      batch_xcv, batch_ycv = mnist.test.next_batch(5000) #simualtes CV data 
      batch_xtest, batch_ytest = mnist.test.next_batch(5000) #simualtes test data 
      # do inference 
      train_error = sess.run(fetches=cross_entropy, feed_dict={x: batch_xs, y_:batch_ys, train_phase: False}) 
      cv_error = sess.run(fetches=cross_entropy, feed_dict={x: batch_xcv, y_:batch_ycv, train_phase: False}) 
      test_error = sess.run(fetches=cross_entropy, feed_dict={x: batch_xtest, y_:batch_ytest, train_phase: False}) 

      def do_stuff_with_errors(*args): 
       print args 
      do_stuff_with_errors(train_error, cv_error, test_error) 
     # Run Train Step 
     sess.run(fetches=train_step, feed_dict={x: batch_xs, y_:batch_ys, train_phase: True}) 
    # list of booleans indicating correct predictions 
    correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) 
    # accuracy 
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) 
    print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels, train_phase: False})) 

私はそれを実行したときに私が手:

Extracting MNIST_data/train-images-idx3-ubyte.gz 
Extracting MNIST_data/train-labels-idx1-ubyte.gz 
Extracting MNIST_data/t10k-images-idx3-ubyte.gz 
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz 
(2.3474066, 2.3498712, 2.3461707) 
(0.49414295, 0.88536006, 0.91152304) 
(0.51632041, 0.393666, nan) 
0.9296 

それはすべての最後のものにするために使用ナンだったと今、それらのほんの数。すべてがうまくやっているのですか?すべての

まず:私はこれで問題が解決するかどうかわからない

+0

https://stackoverflow.com/questions/33949786/how-could-iで私の答えをチェック-use-batch-normalization-in-tensorflow/38325288#38325288。私はまた、最初にそれを試してみたときに散発的にNaNの損失関数を持っていました。私が取り組む2つの問題がありました。1)学習率の低下2)各層のバッチ正規化を保証しました。意味私は入力を隠し層と隠れ層の出力にバッチを正規化します。 –

+0

私がtf.name_scope( 'batch_norm')のようなものを使用すると、スコープ変数をbatch_norm関数に引き渡す必要がありますか? – resistancefm

答えて

6

は、BatchNormのドキュメントは非常に使いやすい/有益ではないので、ここでは簡単なBatchNormを使用する方法の短い要約ですBatchNormレイヤーを定義します。あなたはアフィン/完全に接続された層の後に、それを使用したい場合は、あなたがこれを行う(あなたが望むよう単なる一例を、順番は/異なる場合があります):

... 
inputs = tf.matmul(inputs, W) + b 
inputs = tf.layers.batch_normalization(inputs, training=is_training) 
inputs = tf.nn.relu(inputs) 
... 

可変初期化子を呼び出すtf.layers.batch_normalization機能。これらは内部変数であり、呼び出すには特別なスコープが必要です。これはtf.GraphKeys.UPDATE_OPSです。次のようにそのように、あなたはあなたのオプティマイザの関数を呼び出す必要があります(すべての層が定義された後に!):

... 
extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) 
with tf.control_dependencies(extra_update_ops): 
    trainer = tf.train.AdamOptimizer() 
    updateModel = trainer.minimize(loss, global_step=global_step) 
... 

あなたはそれhereについての詳細を読むことができます。あなたの質問に答えるのは少し遅れたことは分かっていますが、それは他の人がテンソルフローでBatchNormの問題に遭遇するのを助けるかもしれません! :)

0
training =tf.placeholder(tf.bool, name = 'training') 

lr_holder = tf.placeholder(tf.float32, [], name='learning_rate') 
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) 
with tf.control_dependencies(update_ops): 
     optimizer = tf.train.AdamOptimizer(learning_rate = lr).minimize(cost) 

層を定義する際に、プレースホルダを使用する必要がある 'トレーニング'

batchNormal_layer = tf.layers.batch_normalization(pre_batchNormal_layer, training=training)