En muchos códigos de redes neuronales disponibles implementados usando TensorFlow descubrí 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. ¿Existe 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 debe usarse? Según mi observación, si le pasamos un regularizador (como tf.contrib.layers.l2_regularizer, se calculará un tensor que representa el término regularizado y se agregará a una colección de gráficos llamada tf.GraphKeys.REGULARIZATOIN_LOSSES. TensorFlow usará automáticamente esa colección) (p. ej., utilizado por los optimizadores cuando se entrena) ¿O se espera que yo mismo use esa colección?

95
Lifu Huang 9 may. 2016 a las 06:04

8 respuestas

La mejor respuesta

Como dices 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 regularizar todas sus variables.

Las pérdidas se recopilan en el gráfico, y debe agregarlas manualmente a su función de costos 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!

68
Lukasz Kaiser 10 may. 2016 a las 15:47

tf.GraphKeys.REGULARIZATION_LOSSES no se agregará automáticamente, pero hay una manera simple de agregarlos:

reg_loss = tf.losses.get_regularization_loss()
total_loss = loss + reg_loss

tf.losses.get_regularization_loss() usa tf.add_n para sumar las entradas de tf.GraphKeys.REGULARIZATION_LOSSES por elementos. tf.GraphKeys.REGULARIZATION_LOSSES típicamente será una lista de escalares, calculada usando las funciones del regularizador. Obtiene entradas de llamadas a tf.get_variable que tienen el parámetro regularizer especificado. También puede agregar a esa colección manualmente. Eso sería útil al usar tf.Variable y también al especificar regularizadores de actividad u otros regularizadores personalizados. Por ejemplo:

#This will add an activity regularizer on y to the regloss collection
regularizer = tf.contrib.layers.l2_regularizer(0.1)
y = tf.nn.sigmoid(x)
act_reg = regularizer(y)
tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, act_reg)

(En este ejemplo, presumiblemente sería más efectivo regularizar x, ya que y realmente se aplana para x grande).

0
Elias Hasle 25 mar. 2019 a las 11:36

Si tiene CNN, puede hacer lo siguiente:

En la función de su modelo:

conv = tf.layers.conv2d(inputs=input_layer,
                        filters=32,
                        kernel_size=[3, 3],
                        kernel_initializer='xavier',
                        kernel_regularizer=tf.contrib.layers.l2_regularizer(1e-5),
                        padding="same",
                        activation=None) 
...

En su función de pérdida:

onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=num_classes)
loss = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels, logits=logits)
regularization_losses = tf.losses.get_regularization_losses()
loss = tf.add_n([loss] + regularization_losses)
3
tsveti_iko 4 dic. 2018 a las 11:31

Algunas respuestas me confunden más. Aquí les doy dos métodos para aclararlo.

#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 

Luego, se puede agregar a la pérdida total

1
user3201329 29 abr. 2018 a las 09:08

Si alguien sigue buscando, me gustaría agregar que en tf.keras puede agregar regularización de peso pasándola como argumentos en sus capas. Un ejemplo de agregar la regularización L2 tomada al por mayor del sitio de Tutoriales de Keras de Tensorflow:

model = keras.models.Sequential([
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu),
    keras.layers.Dense(1, activation=tf.nn.sigmoid)
])

No hay necesidad de agregar manualmente las pérdidas de regularización con este método, que yo sepa.

Referencia: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#add_weight_regularization

4
MoltenMuffins 25 mar. 2019 a las 08:29
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
Alex-zhai 7 may. 2018 a las 07:51

Probé tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) y tf.losses.get_regularization_loss() con uno l2_regularizer en el gráfico, y descubrí 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.

4
BookOfGreg 25 jul. 2018 a las 13:14

Otra opción para hacer esto con la biblioteca contrib.learn es la siguiente, basada en el tutorial MNIST profundo en el sitio web de Tensorflow. Primero, 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 he vinculado 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 el resultado. Si aplica una regularización como argumento, puede 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 proporciona 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, que muestran los peligros de los términos de alta regularización.

17
ComputerScientist 23 may. 2017 a las 23:55