21

Attualmente sto giocando con ANN che fa parte del corso di Udactity DeepLearning.TensorFlow - introduce sia la regolarizzazione L2 che il dropout nella rete. Ha senso?

Ho costruito con successo e treno rete e introdotto la regolarizzazione L2 su tutti i pesi e pregiudizi. In questo momento sto provando il dropout per il livello nascosto al fine di migliorare la generalizzazione. Mi chiedo, ha senso introdurre entrambi la regolarizzazione L2 nel livello nascosto e il dropout su quello stesso livello? Se sì, come farlo correttamente?

Durante il dropout, interrompiamo letteralmente metà delle attivazioni dello strato nascosto e raddoppiamo la quantità emessa dal resto dei neuroni. Durante l'utilizzo della L2 calcoliamo la norma L2 su tutti i pesi nascosti. Ma non sono sicuro di come calcolare L2 nel caso utilizzassimo il dropout. Interrompiamo alcune attivazioni, non dovremmo rimuovere i pesi che "non vengono usati" ora dal calcolo L2? Qualsiasi riferimento a tale proposito sarà utile, non ho trovato alcuna informazione.

Nel caso in cui si è interessati, il mio codice per ANN con L2 regolarizzazione è qui sotto:

#for NeuralNetwork model code is below 
#We will use SGD for training to save our time. Code is from Assignment 2 
#beta is the new parameter - controls level of regularization. Default is 0.01 
#but feel free to play with it 
#notice, we introduce L2 for both biases and weights of all layers 

beta = 0.01 

#building tensorflow graph 
graph = tf.Graph() 
with graph.as_default(): 
     # Input data. For the training data, we use a placeholder that will be fed 
    # at run time with a training minibatch. 
    tf_train_dataset = tf.placeholder(tf.float32, 
            shape=(batch_size, image_size * image_size)) 
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels)) 
    tf_valid_dataset = tf.constant(valid_dataset) 
    tf_test_dataset = tf.constant(test_dataset) 

    #now let's build our new hidden layer 
    #that's how many hidden neurons we want 
    num_hidden_neurons = 1024 
    #its weights 
    hidden_weights = tf.Variable(
    tf.truncated_normal([image_size * image_size, num_hidden_neurons])) 
    hidden_biases = tf.Variable(tf.zeros([num_hidden_neurons])) 

    #now the layer itself. It multiplies data by weights, adds biases 
    #and takes ReLU over result 
    hidden_layer = tf.nn.relu(tf.matmul(tf_train_dataset, hidden_weights) + hidden_biases) 

    #time to go for output linear layer 
    #out weights connect hidden neurons to output labels 
    #biases are added to output labels 
    out_weights = tf.Variable(
    tf.truncated_normal([num_hidden_neurons, num_labels])) 

    out_biases = tf.Variable(tf.zeros([num_labels])) 

    #compute output 
    out_layer = tf.matmul(hidden_layer,out_weights) + out_biases 
    #our real output is a softmax of prior result 
    #and we also compute its cross-entropy to get our loss 
    #Notice - we introduce our L2 here 
    loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    out_layer, tf_train_labels) + 
    beta*tf.nn.l2_loss(hidden_weights) + 
    beta*tf.nn.l2_loss(hidden_biases) + 
    beta*tf.nn.l2_loss(out_weights) + 
    beta*tf.nn.l2_loss(out_biases))) 

    #now we just minimize this loss to actually train the network 
    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss) 

    #nice, now let's calculate the predictions on each dataset for evaluating the 
    #performance so far 
    # Predictions for the training, validation, and test data. 
    train_prediction = tf.nn.softmax(out_layer) 
    valid_relu = tf.nn.relu( tf.matmul(tf_valid_dataset, hidden_weights) + hidden_biases) 
    valid_prediction = tf.nn.softmax(tf.matmul(valid_relu, out_weights) + out_biases) 

    test_relu = tf.nn.relu(tf.matmul(tf_test_dataset, hidden_weights) + hidden_biases) 
    test_prediction = tf.nn.softmax(tf.matmul(test_relu, out_weights) + out_biases) 



#now is the actual training on the ANN we built 
#we will run it for some number of steps and evaluate the progress after 
#every 500 steps 

#number of steps we will train our ANN 
num_steps = 3001 

#actual training 
with tf.Session(graph=graph) as session: 
    tf.initialize_all_variables().run() 
    print("Initialized") 
    for step in range(num_steps): 
    # Pick an offset within the training data, which has been randomized. 
    # Note: we could use better randomization across epochs. 
    offset = (step * batch_size) % (train_labels.shape[0] - batch_size) 
    # Generate a minibatch. 
    batch_data = train_dataset[offset:(offset + batch_size), :] 
    batch_labels = train_labels[offset:(offset + batch_size), :] 
    # Prepare a dictionary telling the session where to feed the minibatch. 
    # The key of the dictionary is the placeholder node of the graph to be fed, 
    # and the value is the numpy array to feed to it. 
    feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels} 
    _, l, predictions = session.run(
     [optimizer, loss, train_prediction], feed_dict=feed_dict) 
    if (step % 500 == 0): 
     print("Minibatch loss at step %d: %f" % (step, l)) 
     print("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels)) 
     print("Validation accuracy: %.1f%%" % accuracy(
     valid_prediction.eval(), valid_labels)) 
     print("Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels)) 
+6

Perché stai regolarizzando i bias? –

risposta

15

Ok, dopo alcuni ulteriori sforzi sono riuscito a risolvere e introducono sia L2 e di abbandono nella mia rete, codice è sotto. Ho ottenuto un leggero miglioramento sulla stessa rete senza il dropout (con L2 in posizione). Non sono ancora sicuro se valga davvero la pena di introdurre entrambi, L2 e dropout ma almeno funziona e migliora leggermente i risultati.

#ANN with introduced dropout 
#This time we still use the L2 but restrict training dataset 
#to be extremely small 

#get just first 500 of examples, so that our ANN can memorize whole dataset 
train_dataset_2 = train_dataset[:500, :] 
train_labels_2 = train_labels[:500] 

#batch size for SGD and beta parameter for L2 loss 
batch_size = 128 
beta = 0.001 

#that's how many hidden neurons we want 
num_hidden_neurons = 1024 

#building tensorflow graph 
graph = tf.Graph() 
with graph.as_default(): 
    # Input data. For the training data, we use a placeholder that will be fed 
    # at run time with a training minibatch. 
    tf_train_dataset = tf.placeholder(tf.float32, 
            shape=(batch_size, image_size * image_size)) 
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels)) 
    tf_valid_dataset = tf.constant(valid_dataset) 
    tf_test_dataset = tf.constant(test_dataset) 

    #now let's build our new hidden layer 
    #its weights 
    hidden_weights = tf.Variable(
    tf.truncated_normal([image_size * image_size, num_hidden_neurons])) 
    hidden_biases = tf.Variable(tf.zeros([num_hidden_neurons])) 

    #now the layer itself. It multiplies data by weights, adds biases 
    #and takes ReLU over result 
    hidden_layer = tf.nn.relu(tf.matmul(tf_train_dataset, hidden_weights) + hidden_biases) 

    #add dropout on hidden layer 
    #we pick up the probabylity of switching off the activation 
    #and perform the switch off of the activations 
    keep_prob = tf.placeholder("float") 
    hidden_layer_drop = tf.nn.dropout(hidden_layer, keep_prob) 

    #time to go for output linear layer 
    #out weights connect hidden neurons to output labels 
    #biases are added to output labels 
    out_weights = tf.Variable(
    tf.truncated_normal([num_hidden_neurons, num_labels])) 

    out_biases = tf.Variable(tf.zeros([num_labels])) 

    #compute output 
    #notice that upon training we use the switched off activations 
    #i.e. the variaction of hidden_layer with the dropout active 
    out_layer = tf.matmul(hidden_layer_drop,out_weights) + out_biases 
    #our real output is a softmax of prior result 
    #and we also compute its cross-entropy to get our loss 
    #Notice - we introduce our L2 here 
    loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    out_layer, tf_train_labels) + 
    beta*tf.nn.l2_loss(hidden_weights) + 
    beta*tf.nn.l2_loss(hidden_biases) + 
    beta*tf.nn.l2_loss(out_weights) + 
    beta*tf.nn.l2_loss(out_biases))) 

    #now we just minimize this loss to actually train the network 
    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss) 

    #nice, now let's calculate the predictions on each dataset for evaluating the 
    #performance so far 
    # Predictions for the training, validation, and test data. 
    train_prediction = tf.nn.softmax(out_layer) 
    valid_relu = tf.nn.relu( tf.matmul(tf_valid_dataset, hidden_weights) + hidden_biases) 
    valid_prediction = tf.nn.softmax(tf.matmul(valid_relu, out_weights) + out_biases) 

    test_relu = tf.nn.relu(tf.matmul(tf_test_dataset, hidden_weights) + hidden_biases) 
    test_prediction = tf.nn.softmax(tf.matmul(test_relu, out_weights) + out_biases) 



#now is the actual training on the ANN we built 
#we will run it for some number of steps and evaluate the progress after 
#every 500 steps 

#number of steps we will train our ANN 
num_steps = 3001 

#actual training 
with tf.Session(graph=graph) as session: 
    tf.initialize_all_variables().run() 
    print("Initialized") 
    for step in range(num_steps): 
    # Pick an offset within the training data, which has been randomized. 
    # Note: we could use better randomization across epochs. 
    offset = (step * batch_size) % (train_labels_2.shape[0] - batch_size) 
    # Generate a minibatch. 
    batch_data = train_dataset_2[offset:(offset + batch_size), :] 
    batch_labels = train_labels_2[offset:(offset + batch_size), :] 
    # Prepare a dictionary telling the session where to feed the minibatch. 
    # The key of the dictionary is the placeholder node of the graph to be fed, 
    # and the value is the numpy array to feed to it. 
    feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, keep_prob : 0.5} 
    _, l, predictions = session.run(
     [optimizer, loss, train_prediction], feed_dict=feed_dict) 
    if (step % 500 == 0): 
     print("Minibatch loss at step %d: %f" % (step, l)) 
     print("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels)) 
     print("Validation accuracy: %.1f%%" % accuracy(
     valid_prediction.eval(), valid_labels)) 
     print("Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels)) 
+0

Il documento originale in caso di interruzione chiama in modo specifico questo tipo di configurazione, quindi probabilmente stai cercando di farlo. Anche se potrei notare che non penso sia normale includere la regolarizzazione L2 sui bias, solo sui pesi. http://www.jmlr.org/papers/volume15/srivastava14a.old/source/srivastava14a.pdf http://stats.stackexchange.com/questions/153605/no-regularisation-term-for-bias-unit- rete interna neurale –

+1

@DavidParks Sembra che sia necessario includere anche L2 nei bias.Per favore, date un'occhiata all'esempio di tensorflow MNIST qui: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/models/image/mnist/convolutional.py Cerca chiamate di funzione 'l2_loss'. –

+1

Prendi questo come esempio: Abbiamo una singola caratteristica x, ed è valori y, e eseguiamo un adattamento lineare ai dati, y = mx + b. Se tutti i punti di dati si raggruppano attorno a y = 1000 con una piccola varianza, avremo bisogno di una grande distorsione per spostare la linea fino a 1000. Questo non è un problema per cui adeguarsi, è solo il punto in cui si trovano i dati. Il problema è quando sovrapponiamo una funzionalità. Il pregiudizio è solo un offset. Detto questo, ho recentemente tracciato un istogramma di pesi e pregiudizi sui problemi di classificazione e regressione e in entrambi i casi non ho visto pregiudizi che erano grandi. Quindi dubito che stia causando un problema evidente. –

4

In realtà, il lavoro originale utilizza max-norma regolarizzazione, e non L2, oltre alla forcellino:. "La rete neurale è stato ottimizzato sotto il vincolo || w || 2 ≤ c Questa vincolo era imposto durante l'ottimizzazione proiettando w sulla superficie di una sfera di raggio c, ogni volta che ne è uscito. Questa è anche chiamata regolarizzazione massima della norma poiché implica che il valore massimo che la norma di qualsiasi peso può assumere è c "(http://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf)

Qui puoi trovare una bella discussione su questo metodo di regolarizzazione: https://plus.google.com/+IanGoodfellow/posts/QUaCJfvDpni

5

Non c'è nessun lato negativo per utilizzare più regolarizzazioni. In effetti c'è un documento Dropout: A Simple Way to Prevent Neural Networks from Overfitting in cui gli autori hanno controllato quanto aiuta. Chiaramente per i diversi set di dati si avrà risultati diversi, ma per il vostro MNIST:

enter image description here

si può vedere che Dropout + Max-norm dà l'errore più basso. A parte questo hai un grande errore nel tuo codice.

Si utilizza l2_loss sui pesi e pregiudizi:

beta*tf.nn.l2_loss(hidden_weights) + 
beta*tf.nn.l2_loss(hidden_biases) + 
beta*tf.nn.l2_loss(out_weights) + 
beta*tf.nn.l2_loss(out_biases))) 

Si consiglia di non penalizzare le alte pregiudizi. Quindi rimuovere l2_loss su bias.