web-dev-qa-db-fra.com

TensorFlow - régularisation avec perte de L2, comment s’appliquer à tous les poids, pas seulement au dernier?

Je joue avec un ANN qui fait partie du cours Udacity DeepLearning.

J'ai une tâche qui consiste à introduire la généralisation au réseau avec une couche ReLU cachée utilisant une perte L2. Je me demande comment l'introduire correctement pour que TOUS les poids soient pénalisés, pas seulement les poids de la couche de sortie.

Code pour le réseau sans la généralisation est au bas de la poste (le code pour réellement exécuter la formation est en dehors du champ de la question).

Une façon évidente d’introduire la L2 consiste à remplacer le calcul de la perte par quelque chose comme ceci (si la version bêta est 0,01):

loss = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(out_layer, tf_train_labels) + 0.01*tf.nn.l2_loss(out_weights))

Mais dans ce cas, il tiendra compte des valeurs des pondérations de la couche de sortie. Je ne sais pas trop comment pénaliser correctement les poids entrant dans la couche cachée de ReLU. Est-il vraiment nécessaire ou une pénalisation de la couche de sortie permettra-t-elle également de contrôler les poids cachés?

#some importing
from __future__ import print_function
import numpy as np
import tensorflow as tf
from six.moves import cPickle as pickle
from six.moves import range

#loading data
pickle_file = '/home/maxkhk/Documents/Udacity/DeepLearningCourse/SourceCode/tensorflow/examples/udacity/notMNIST.pickle'

with open(pickle_file, 'rb') as f:
  save = pickle.load(f)
  train_dataset = save['train_dataset']
  train_labels = save['train_labels']
  valid_dataset = save['valid_dataset']
  valid_labels = save['valid_labels']
  test_dataset = save['test_dataset']
  test_labels = save['test_labels']
  del save  # hint to help gc free up memory
  print('Training set', train_dataset.shape, train_labels.shape)
  print('Validation set', valid_dataset.shape, valid_labels.shape)
  print('Test set', test_dataset.shape, test_labels.shape)


#prepare data to have right format for tensorflow
#i.e. data is flat matrix, labels are onehot

image_size = 28
num_labels = 10

def reformat(dataset, labels):
  dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)
  # Map 0 to [1.0, 0.0, 0.0 ...], 1 to [0.0, 1.0, 0.0 ...]
  labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)
  return dataset, labels
train_dataset, train_labels = reformat(train_dataset, train_labels)
valid_dataset, valid_labels = reformat(valid_dataset, valid_labels)
test_dataset, test_labels = reformat(test_dataset, test_labels)
print('Training set', train_dataset.shape, train_labels.shape)
print('Validation set', valid_dataset.shape, valid_labels.shape)
print('Test set', test_dataset.shape, test_labels.shape)


#now is the interesting part - we are building a network with
#one hidden ReLU layer and out usual output linear layer

#we are going to use SGD so here is our size of batch
batch_size = 128

#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
  loss = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(out_layer, tf_train_labels))

  #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)
59
Maksim Khaitovich

hidden_weights, hidden_biases, out_weights et out_biases sont tous les paramètres de modèle que vous créez. Vous pouvez ajouter une régularisation L2 à TOUS ces paramètres comme suit:

loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits=out_layer, labels=tf_train_labels)) +
    0.01*tf.nn.l2_loss(hidden_weights) +
    0.01*tf.nn.l2_loss(hidden_biases) +
    0.01*tf.nn.l2_loss(out_weights) +
    0.01*tf.nn.l2_loss(out_biases))
56
keveman

Une manière plus courte et évolutive de le faire serait:

vars   = tf.trainable_variables() 
lossL2 = tf.add_n([ tf.nn.l2_loss(v) for v in vars ]) * 0.001

Ceci résume en gros la perte de l2 de toutes vos variables pouvant être entraînées. Vous pouvez également créer un dictionnaire dans lequel vous spécifiez uniquement les variables que vous souhaitez ajouter à votre coût et utilisez la deuxième ligne ci-dessus. Ensuite, vous pouvez ajouter lossL2 avec votre valeur d'entropie croisée softmax afin de calculer votre perte totale.

Edit: Comme mentionné par Piotr Dabkowski, le code ci-dessus régularisera également les biais . Cela peut être évité en ajoutant une instruction if dans la deuxième ligne;

lossL2 = tf.add_n([ tf.nn.l2_loss(v) for v in vars
                    if 'bias' not in v.name ]) * 0.001

Ceci peut être utilisé pour exclure d'autres variables.

98
PhABC

En fait, nous ne régularisons généralement pas les termes biaisés (intercepts). Donc, je vais pour:

loss = (tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits=out_layer, labels=tf_train_labels)) +
    0.01*tf.nn.l2_loss(hidden_weights) +
    0.01*tf.nn.l2_loss(out_weights))

En pénalisant le terme d'interception, au fur et à mesure que l'interception est ajoutée aux valeurs y, il en résultera une modification des valeurs y, en ajoutant une constante c aux conversations interceptées. Avoir ou non ne changera pas les résultats mais prend quelques calculs

16
Yousof Erfani