¿Cómo agregar regularizaciones en TensorFlow?


Encontré en muchos códigos de redes neuronales disponibles implementados usando TensorFlow que los términos de regularización a menudo se implementan agregando manualmente un término adicional al valor de pérdida.

Mis preguntas son:

  1. ¿Hay una forma más elegante o recomendada de regularización que hacerlo manualmente?

  2. También encuentro que get_variable tiene un argumento regularizer. ¿Cómo se debe utilizar? Según mi observación, si le pasamos un regularizador (como tf.contrib.layers.l2_regularizer, un tensor la representación del término regularizado se calculará y se agregará a una colección de gráficos llamada tf.GraphKeys.REGULARIZATOIN_LOSSES. ¿TensorFlow utilizará esa colección automáticamente (por ejemplo, utilizada por optimizadores durante el entrenamiento)? ¿O se espera que use esa colección yo solo?

Author: Augustin, 2016-05-09

7 answers

Como dice en el segundo punto, usar el argumento regularizer es la forma recomendada. Puede usarlo en get_variable, o configurarlo una vez en su variable_scope y tener todas sus variables regularizadas.

Las pérdidas se recogen en el gráfico, y debe agregarlas manualmente a su función de costo de esta manera.

  reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
  reg_constant = 0.01  # Choose an appropriate one.
  loss = my_normal_loss + reg_constant * sum(reg_losses)

¡Espero que eso ayude!

 52
Author: Lukasz Kaiser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-10 15:47:09

Algunos aspectos de la respuesta existente no fueron inmediatamente claros para mí, así que aquí hay una guía paso a paso:

  1. Define un regularizador. Aquí es donde se puede establecer la constante de regularización, por ejemplo:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
    
  2. Crear variables a través de:

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

    De forma equivalente, las variables se pueden crear a través del constructor regular weights = tf.Variable(...), seguido de tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights).

  3. Defina algún término loss y agregue el término de regularización:

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

    Nota: parece que tf.contrib.layers.apply_regularization se implementa como un AddN, por lo que más o menos equivalente a sum(reg_variables).

 32
Author: bluenote10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-10 16:50:23

Otra opción para hacer esto con la biblioteca contrib.learn es la siguiente, basada en el tutorial Deep MNIST en el sitio web de Tensorflow. En primer lugar, suponiendo que haya importado las bibliotecas relevantes (como import tensorflow.contrib.layers as layers), puede definir una red en un método separado:

def easier_network(x, reg):
    """ A network based on tf.contrib.learn, with input `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, # Because there are ten digits!
                weights_initializer = layers.xavier_initializer(uniform=True),
                weights_regularizer = layers.l2_regularizer(scale=reg),
                activation_fn = None)
        return out 

Luego, en un método principal, puede usar el siguiente fragmento de código:

def main(_):
    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])

    # Make a network with regularization
    y_conv = easier_network(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("")

    # Make the loss function `loss_fn` with regularization.
    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)

Para que esto funcione, debe seguir el tutorial MNIST al que enlacé anteriormente e importar las bibliotecas relevantes, pero es un buen ejercicio para aprender TensorFlow y es fácil ver cómo la regularización afecta a la salida. Si aplicas una regularización como argumento, puedes ver lo siguiente:

- 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

Tenga en cuenta que la parte de regularización le da tres elementos, en función de los elementos disponibles.

Con regularizaciones de 0, 0.0001, 0.01 y 1.0, obtengo valores de precisión de prueba de 0.9468, 0.9476, 0.9183 y 0.1135, respectivamente, mostrando los peligros de los términos de alta regularización.

 15
Author: ComputerScientist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 23:55:08

Daré una respuesta correcta simple ya que no encontré una. Necesitas dos sencillos pasos, el resto lo hace tensorflow magic:

  1. Agregue regularizadores al crear variables o capas:

    tf.layers.dense(x, kernel_regularizer=tf.contrib.layers.l2_regularizer(0.001))
    # or
    tf.get_variable('a', regularizer=tf.contrib.layers.l2_regularizer(0.001))
    
  2. Añadir el término de regularización al definir la pérdida:

    loss = ordinary_loss + tf.losses.get_regularization_loss()
    
 15
Author: alyaxey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-31 13:35:44

Probé tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) y tf.losses.get_regularization_loss() con un l2_regularizer en el gráfico, y encontré que devuelven el mismo valor. Al observar la cantidad del valor, supongo que reg_constant ya tiene sentido en el valor al establecer el parámetro de tf.contrib.layers.l2_regularizer.

 2
Author: ocean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-25 13:14:18

Algunas respuestas me confunden más.Aquí doy dos métodos para hacerlo claramente.

#1.adding all regs by hand
var1 = tf.get_variable(name='v1',shape=[1],dtype=tf.float32)
var2 = tf.Variable(name='v2',initial_value=1.0,dtype=tf.float32)
regularizer = tf.contrib.layers.l1_regularizer(0.1)
reg_term = tf.contrib.layers.apply_regularization(regularizer,[var1,var2])
#here reg_term is a scalar

#2.auto added and read,but using get_variable
with tf.variable_scope('x',
        regularizer=tf.contrib.layers.l2_regularizer(0.1)):
    var1 = tf.get_variable(name='v1',shape=[1],dtype=tf.float32)
    var2 = tf.get_variable(name='v2',shape=[1],dtype=tf.float32)
reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
#here reg_losses is a list,should be summed 

Entonces, se puede agregar a la pérdida total

 1
Author: user3201329,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-29 09:08:24
cross_entropy = tf.losses.softmax_cross_entropy(
  logits=logits, onehot_labels=labels)

l2_loss = weight_decay * tf.add_n(
     [tf.nn.l2_loss(tf.cast(v, tf.float32)) for v in tf.trainable_variables()])

loss = cross_entropy + l2_loss
 1
Author: Alex-zhai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-07 07:51:32