95 votes

Comment ajouter des régularisations dans TensorFlow ?

J'ai trouvé dans de nombreux codes de réseaux neuronaux disponibles implémentés en utilisant TensorFlow que les termes de régularisation sont souvent implémentés en ajoutant manuellement un terme supplémentaire à la valeur de perte.

Mes questions sont les suivantes:

  1. Existe-t-il une façon plus élégante ou recommandée de réaliser la régularisation plutôt que de le faire manuellement?

  2. J'ai également remarqué que get_variable a un argument regularizer. Comment devrait-il être utilisé? D'après ce que j'ai observé, si nous lui passons un régulariseur (comme tf.contrib.layers.l2_regularizer), un tenseur représentant le terme régularisé sera calculé et ajouté à une collection de graphiques nommée tf.GraphKeys.REGULARIZATOIN_LOSSES. Cette collection sera-t-elle automatiquement utilisée par TensorFlow (par exemple, utilisée par les optimiseurs lors de l'apprentissage)? Ou est-il prévu que je devrais utiliser cette collection par moi-même?

1 votes

Juste pour être super explicite, est-ce que la façon de le faire est S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer ) ?

0 votes

@Pinocchio l'as-tu compris?

2 votes

@Euler_Salter Je ne m'en souviens plus, désolé ! Je n'utilise plus tensor flow maintenant !

70voto

Lukasz Kaiser Points 1820

Comme vous le dites dans le deuxième point, l'utilisation de l'argument regularizer est la méthode recommandée. Vous pouvez l'utiliser dans get_variable, ou le définir une fois dans votre variable_scope et avoir toutes vos variables régularisées.

Les pertes sont collectées dans le graphique, et vous devez les ajouter manuellement à votre fonction de coût comme ceci.

  reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
  reg_constant = 0.01  # Choisissez une valeur appropriée.
  loss = my_normal_loss + reg_constant * sum(reg_losses)

J'espère que cela vous sera utile!

2 votes

Merci mec. Je pensais que TensorFlow aurait des moyens plus intelligents de gérer les termes de régularisation que de les faire manuellement, il semble que non :P

14 votes

Au fait, deux suggestions, corrigez-moi si je me trompe. (1), Je suppose que reg_constant pourrait ne pas être nécessaire, car les régularisateurs dans TensorFlow ont un argument scale dans leurs constructeurs de sorte que l'impact des termes de régularisation peut être contrôlé de manière plus fine. Et (2) l'utilisation de tf.add_n pourrait être légèrement meilleure que sum, je suppose que l'utilisation de sum pourrait créer de nombreux tenseurs dans le graphe pour stocker le résultat intermédiaire.

1 votes

Donc juste pour être bien clair, après avoir mis le régularisateur sur la variable S = tf.get_variable(name='S', regularizer=tf.contrib.layers.l2_regularizer ), est-ce que je fais le code que vous avez suggéré? Comme dans sum(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)) ?

46voto

bluenote10 Points 1932

Quelques aspects de la réponse existante ne m'étaient pas immédiatement clairs, voici donc un guide étape par étape :

  1. Définissez un régulariseur. C'est ici que la constante de régularisation peut être définie, par exemple :

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
  2. Créez des variables via :

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

    De manière équivalente, les variables peuvent être créées via le constructeur régulier weights = tf.Variable(...), suivi de tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights).

  3. Définissez un terme de perte loss et ajoutez le terme de régularisation :

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

    Remarque : Il semble que tf.contrib.layers.apply_regularization soit implémenté comme un AddN, donc plus ou moins équivalent à sum(reg_variables).

10 votes

Je pense que vous appliquez le régulariseur deux fois - à la fois à l'étape et à l'étape 3. appliquer_la_régularisation ne devrait pas être nécessaire si vous avez déjà spécifié le régulariseur lors de la création de la variable.

2 votes

@interjay s'il vous plaît faites un exemple, toutes ces réponses sont super peu claire! C'est parce qu'il y a toujours au moins une personne qui écrit un commentaire en dessous en disant que la réponse ci-dessus a quelque chose de faux.

1 votes

@interjay Je suis presque sûr que faire les deux était nécessaire la dernière fois que j'ai testé cela. Je ne suis pas sûr si cela a changé cependant.

28voto

alyaxey Points 512

Je vais fournir une réponse correcte et simple car je n'en ai pas trouvé. Vous avez besoin de deux étapes simples, le reste est fait par la magie de tensorflow :

  1. Ajoutez des régularisateurs lors de la création de variables ou de couches :

    tf.layers.dense(x, kernel_regularizer=tf.contrib.layers.l2_regularizer(0.001))
    # ou
    tf.get_variable('a', regularizer=tf.contrib.layers.l2_regularizer(0.001))
  2. Ajoutez le terme de régularisation lors de la définition de la perte :

    loss = ordinary_loss + tf.losses.get_regularization_loss()

0 votes

Si je crée une opération de régularisation en régulier = tf.contrib.layers.l2_regularizer(0.001), puis-je la passer à plusieurs initialisations de couches ? Ou dois-je créer une régularisation distincte pour chaque couche comme régularizer1 = tf.contrib.layers.l2_regularizer(0.001), régularizer2 = ................. régularizer3 = ...... et ainsi de suite ?

0 votes

@Nitin Vous pouvez utiliser le même régulariseur. C'est juste une fonction python qui applique une perte aux poids en tant qu'argument.

1 votes

Cela ressemble à la solution la plus élégante mais est-ce que cela fonctionne vraiment? En quoi cela est-il différent de dire reg_variables = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) reg_term = tf.contrib.layers.apply_regularization(regularizer, reg_variables) loss += reg_term

16voto

ComputerScientist Points 463

Une autre option pour réaliser cela avec la bibliothèque contrib.learn est la suivante, basée sur le tutoriel Deep MNIST sur le site de Tensorflow. Tout d'abord, en supposant que vous avez importé les bibliothèques pertinentes (telles que import tensorflow.contrib.layers as layers), vous pouvez définir un réseau dans une méthode séparée :

def reseau_plus_facile(x, reg):
    """ Un réseau basé sur tf.contrib.learn, avec l'entrée `x`. """
    with tf.variable_scope('EasyNet'):
        out = layers.flatten(x)
        out = layers.fully_connected(out, 
                num_outputs=200,
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = tf.nn.tanh)
        out = layers.fully_connected(out, 
                num_outputs=200,
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = tf.nn.tanh)
        out = layers.fully_connected(out, 
                num_outputs=10, # Parce qu'il y a dix chiffres!
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = None)
        return out 

Ensuite, dans une méthode principale, vous pouvez utiliser le code suivant :

def principal(_):
    mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
    x = tf.placeholder(tf.float32, [None, 784])
    y_ = tf.placeholder(tf.float32, [None, 10])

    # Créer un réseau avec régularisation
    y_conv = reseau_plus_facile(x, FLAGS.regu)
    weights = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, 'EasyNet') 
    print("")
    for w in weights:
        shp = w.get_shape().as_list()
        print("- {} shape:{} size:{}".format(w.name, shp, np.prod(shp)))
    print("")
    reg_ws = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES, 'EasyNet')
    for w in reg_ws:
        shp = w.get_shape().as_list()
        print("- {} shape:{} size:{}".format(w.name, shp, np.prod(shp)))
    print("")

    # Créer la fonction de perte `loss_fn` avec régularisation.
    cross_entropy = tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
    loss_fn = cross_entropy + tf.reduce_sum(reg_ws)
    train_step = tf.train.AdamOptimizer(1e-4).minimize(loss_fn)

Pour que cela fonctionne, vous devez suivre le tutoriel MNIST auquel j'ai donné un lien précédemment et importer les bibliothèques pertinentes, mais c'est un bel exercice pour apprendre TensorFlow et il est facile de voir comment la régularisation affecte la sortie. Si vous appliquez une régularisation en tant qu'argument, vous obtenez ce qui suit :

- EasyNet/fully_connected/weights:0 shape:[784, 200] size:156800
- EasyNet/fully_connected/biases:0 shape:[200] size:200
- EasyNet/fully_connected_1/weights:0 shape:[200, 200] size:40000
- EasyNet/fully_connected_1/biases:0 shape:[200] size:200
- EasyNet/fully_connected_2/weights:0 shape:[200, 10] size:2000
- EasyNet/fully_connected_2/biases:0 shape:[10] size:10

- EasyNet/fully_connected/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0
- EasyNet/fully_connected_1/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0
- EasyNet/fully_connected_2/kernel/Regularizer/l2_regularizer:0 shape:[] size:1.0

Remarquez que la partie régularisation vous donne trois éléments, basés sur les éléments disponibles.

Avec des régularisations de 0, 0.0001, 0.01 et 1.0, j'obtiens des valeurs de précision de test de 0.9468, 0.9476, 0.9183 et 0.1135, respectivement, montrant les dangers des termes de régularisation élevés.

2 votes

Vraiment exemple détaillé.

4voto

ocean Points 21

J'ai testé tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) et tf.losses.get_regularization_loss() avec un l2_regularizer dans le graphe, et j'ai trouvé qu'ils retournent la même valeur. En observant la quantité de la valeur, je suppose que reg_constant a déjà du sens sur la valeur en définissant le paramètre de tf.contrib.layers.l2_regularizer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X