5

Stavo cercando di utilizzare la normalizzazione batch per addestrare le reti neurali usando TensorFlow ma non mi è chiaro come utilizzare the official layer implementation of Batch Normalization (nota che è diverso da quello dello API).Come si usa il livello di normalizzazione batch in TensorFlow?

Dopo alcuni scavi dolorosi sul loro github issues sembra che uno abbia bisogno di un tf.cond per usarlo correttamente e anche un flag 'resue = True' in modo che le variabili di spostamento e scala del BN siano riutilizzate correttamente. Dopo averlo capito, ho fornito una piccola descrizione di come credo sia il modo giusto di usarlo here.

Ora ho scritto un breve script per testarlo (solo un singolo livello e un ReLu, difficile renderlo più piccolo di questo). Tuttavia, non sono sicuro al 100% come testarlo. In questo momento il mio codice funziona senza messaggi di errore, ma restituisce NaNs in modo imprevisto. Ciò mi fa abbassare la fiducia che il codice che ho dato nell'altro post possa essere corretto. O forse la rete che ho è strana. In ogni caso, qualcuno sa che cosa non va? Ecco il codice:

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

quando l'eseguo ottengo:

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 

ha usato per essere tutti gli ultimi erano nan e ora solo alcuni di loro. Va tutto bene o sono paranoico?

+0

Controllare la mia risposta in https://stackoverflow.com/questions/33949786/how-could-i -utilizzare-batch-normalizzazione-in-tensorflow/38325288 # 38325288. Ho anche avuto un NaN in funzione di perdita sporadicamente quando inizialmente l'ho provato e c'erano 2 problemi che ho affrontato: 1) Tasso di apprendimento ridotto 2) Garantito che la normalizzazione del lotto sia eseguita per OGNI strato. Significato I lotto normalizza l'input al livello nascosto e l'output del livello nascosto. –

+0

Se uso qualcosa come: con tf.name_scope ('batch_norm'), è ancora necessario passare la variabile scope alla funzione batch_norm? – resistancefm

risposta

6

Io non sono sicuro se questo risolverà il vostro problema, la documentazione per BatchNorm non è abbastanza facile da usare/informativo, ecco un breve riassunto su come utilizzare semplice BatchNorm:

Prima di tutto , definisci il tuo livello BatchNorm. Se si desidera utilizzarlo dopo un/strato completamente connessa affine, si esegue questa operazione (solo un esempio, l'ordine può essere diverso/come volete):

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

La funzione tf.layers.batch_normalization chiama variabile-inizializzatori. Queste sono variabili interne e richiedono un ambito speciale per essere chiamati, che è nello tf.GraphKeys.UPDATE_OPS. Come tale, è necessario chiamare la funzione di ottimizzazione nel modo seguente (dopo tutti i livelli sono stati definiti!):

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

Si può leggere di più su di esso here. So che è un po 'tardi per rispondere alla tua domanda, ma potrebbe aiutare gli altri a venire incontro ai problemi di BatchNorm in tensorflow! :)

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) 

quando si definiscono i livelli, è necessario utilizzare il segnaposto 'training'

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