web-dev-qa-db-fra.com

Ajouter une régularisation L2 lors de l'utilisation de couches de haut niveau

Est-il possible d'ajouter une régularisation L2 en utilisant les calques définis dans tf.layers? 

Il me semble que, puisque tf.layers est un wrapper de haut niveau, il n’existe aucun moyen facile d’avoir accès aux poids de filtrage.

Avec tf.nn.conv2d

regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)

weights = tf.get_variable(
    name="weights",
    regularizer=regularizer
)

#Previous layers

...

#Second layer 
layer 2 = tf.nn.conv2d(
input,
weights,
[1,1,1,1],
[1,1,1,1])

#More layers
...

#Loss
loss = #some loss

reg_variables = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
reg_term = tf.contrib.layers.apply_regularization(regularizer, reg_variables)
loss += reg_term

Maintenant, à quoi ressemblerait-il avec tf.layers.conv2d?

Merci!

21
Malo Marrec

Vous pouvez les passer dans tf.layers.conv2d comme arguments:

regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
layer2 = tf.layers.conv2d(
    inputs,
    filters,
    kernel_size,
    kernel_regularizer=regularizer)

Ensuite, vous devriez ajouter la perte de régularisation à votre perte comme ceci:

l2_loss = tf.losses.get_regularization_loss()
loss += l2_loss

Edit: Merci Zeke Arneodo, Tom et srcolinas, j’ai ajouté, le dernier commentaire sur vos commentaires afin que la réponse acceptée apporte la solution complète.

24
Robert Lacok

La réponse n'est-elle pas dans votre question? Vous pouvez également utiliser tf.losses.get_regularization_loss ( https://www.tensorflow.org/api_docs/python/tf/losses/get_normalisation_loss ), qui collectera tous les REGULARIZATION_LOSSES.

...
layer2 = tf.layers.conv2d(input, 
     filters, 
     kernel_size,                        
     kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.1))
...
l2_loss = tf.losses.get_regularization_loss()
loss += l2_loss
16
Zeke Arneodo

Je vois deux réponses incomplètes, alors voici la complète:

regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
    layer2 = tf.layers.conv2d(
        inputs,
        filters,
        kernel_size,
        kernel_regularizer=regularizer)

alternativement:

layer2 = tf.layers.conv2d(inputs, 
     filters, 
     kernel_size,                        
     kernel_regularizer= tf.contrib.layers.l2_regularizer(scale=0.1))

n'oubliez pas de l'ajouter à la perte finale:

l2_loss = tf.losses.get_regularization_loss()
....
loss += l2_loss

En gros, ajoutez une régularisation lorsque vous définissez une couche, puis assurez-vous d’ajouter une perte de régularisation à votre perte.

2
srcolinas

Dans une exécution avide, il y a deux façons.

  1. Calculez à la main avec tf.add_n([tf.square(i) for i in layer.variables]) * l2_coef.
  2. Utiliser layer.losses lorsque le calque est créé avec kernel_regularizer.

Comme indiqué dans les exemples officiels: densenet_test.py

Rand_input = tf.random_uniform((10, 3, 32, 32))
weight_decay = 1e-4

conv = tf.keras.layers.Conv2D(
    3, (3, 3),
    padding='same',
    use_bias=False,
    kernel_regularizer=tf.keras.regularizers.l2(weight_decay))

optimizer = tf.train.GradientDescentOptimizer(0.1)
conv(Rand_input)  # Initialize the variables in the layer

def compute_true_l2(vs, wd):
  return tf.reduce_sum(tf.square(vs)) * wd

true_l2 = compute_true_l2(conv.variables, weight_decay)
keras_l2 = tf.add_n(conv.losses)
self.assertAllClose(true_l2, keras_l2)

with tf.GradientTape() as tape_true, tf.GradientTape() as tape_keras:
  loss = tf.reduce_sum(conv(Rand_input))
  loss_with_true_l2 = loss + compute_true_l2(conv.variables, weight_decay)
  loss_with_keras_l2 = loss + tf.add_n(conv.losses)

true_grads = tape_true.gradient(loss_with_true_l2, conv.variables)
keras_grads = tape_keras.gradient(loss_with_keras_l2, conv.variables)
self.assertAllClose(true_grads, keras_grads)
0
ywfu