5

Ich habe versucht, Batch-Normalisierung verwenden, um meine neuronalen Netze mit TensorFlow zu trainieren, aber es war mir unklar, wie man the official layer implementation of Batch Normalization verwenden (beachten Sie, dass dies von der aus der API unterscheidet).Wie benutzt man die offizielle Schichtnormalisierungsschicht in TensorFlow?

Nach einigen schmerzhaften Graben auf ihre github issues scheint es, dass man eine tf.cond braucht, um es richtig zu verwenden und auch eine "resue = True" -Flag, so dass die BN-Verschiebung und Maßstab Variablen ordnungsgemäß wiederverwendet werden. Nachdem ich das herausgefunden hatte, lieferte ich eine kleine Beschreibung, wie ich glaube, dass es der richtige Weg ist, es zu benutzen. here.

Jetzt habe ich ein kurzes Skript geschrieben, um es zu testen (nur eine einzelne Schicht und ein ReLu, schwer, es kleiner als das zu machen). Ich bin jedoch nicht 100% sicher, wie ich es testen soll. Momentan läuft mein Code ohne Fehlermeldung, gibt aber unerwartet NaNs zurück. Das senkt mein Vertrauen, dass der Code, den ich in dem anderen Beitrag gegeben habe, richtig sein könnte. Oder vielleicht ist das Netzwerk, das ich habe, komisch. Wie auch immer, weiß jemand, was falsch ist? Hier ist der Code:

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})) 

wenn ich es benutze ich:

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 

es verwendet, um alle die letzten zu sein, waren nan und jetzt nur ein paar von ihnen. Ist alles in Ordnung oder bin ich paranoisch?

+0

Überprüfen Sie meine Antwort in https://stackoverflow.com/questions/33949786/how-could-i -Nutzung-Batch-Normalisierung-in-Tensor-Flow/38325288 # 38325288. Ich hatte auch eine NaN in Verlustfunktion sporadisch, als ich es zuerst versuchte und es gab 2 Probleme, die ich ansprach: 1) Verringerte Lernrate 2) Sichergestellt, dass die Stapelnormierung für JEDE Schicht durchgeführt wird. Das bedeutet, dass ich die Eingabe für die ausgeblendete Ebene und die Ausgabe der ausgeblendeten Ebene normalisiere. –

+0

Wenn ich etwas wie verwende: mit tf.name_scope ('batch_norm'), ist es noch notwendig, die Scope-Variable an die Batch-Norm-Funktion übergeben? – resistancefm

Antwort

6

Ich bin nicht sicher, ob dies Ihr Problem lösen wird, die Dokumentation für BatchNorm ist nicht ganz einfach zu bedien/informativ, ist so hier eine kurze Rekapitulation auf, wie einfach BatchNorm verwenden:

Zu allererst Definieren Sie Ihre BatchNorm-Ebene. Wenn Sie es nach einer affinen/vollständig verbundene Schicht verwenden möchten, können Sie dies tun (nur ein Beispiel, kann Auftrag unterschiedlich sein/wie Sie wünschen):

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

Die Funktion tf.layers.batch_normalization variabler initializers nennt. Dies sind interne Variablen und müssen einen speziellen Bereich aufrufen, der in der tf.GraphKeys.UPDATE_OPS steht. Als solche müssen Sie Ihre Optimierer Funktion wie folgt aufrufen (nachdem alle Schichten definiert wurden!):

... 
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) 
... 

Sie können here mehr darüber lesen. Ich weiß, es ist ein bisschen spät, um Ihre Frage zu beantworten, aber es könnte anderen Leuten helfen, auf BatchNorm-Probleme im Tensorflow zu stoßen! :)

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) 

wenn die Schichten definieren, müssen Sie den Platzhalter 'Ausbildung' verwenden

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