Как добавить регуляризации в TensorFlow?

Во многих доступных кодах нейронной сети, реализованных с использованием TensorFlow, я обнаружил, что термины регуляризации часто реализуются путем добавления дополнительного члена к значению потерь вручную.

Мои вопросы:

  1. Есть ли более элегантный или рекомендуемый способ регуляризации, чем делать это вручную?

  2. Я также обнаружил, что у get_variable есть аргумент regularizer. Как это должно быть использовано? Согласно моим наблюдениям, если мы передадим ему регуляризатор (например, tf.contrib.layers.l2_regularizer, тензор, представляющий регуляризованный член, будет вычислен и добавлен к коллекция графов с именем tf.GraphKeys.REGULARIZATOIN_LOSSES. Будет ли эта коллекция автоматически использоваться TensorFlow (например, использоваться оптимизаторами при обучении)? Или ожидается, что я должен использовать эту коллекцию сам?

79 голосов | спросил Lifu Huang 9 Mayam16 2016, 06:04:56

8 ответов


0

Как вы говорите во втором пункте, рекомендуется использовать аргумент regularizer. Вы можете использовать его в get_variable или установить его один раз в variable_scope и все ваши переменные будут упорядочены.

Потери собраны на графике, и вам нужно вручную добавить их в свою функцию стоимости следующим образом.

  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)

Надеюсь, это поможет!

ответил Lukasz Kaiser 10 Maypm16 2016, 18:47:09
0

Некоторые аспекты существующего ответа не были сразу понятны мне, так что вот пошаговое руководство:

  1. Определите регуляризатор. Здесь можно установить константу регуляризации, например:

    regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
    
  2. Создать переменные через:

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

    Эквивалентно, переменные могут быть созданы с помощью обычного конструктора weights = tf.Variable(...), за которым следует tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights)

  3. Определите некоторый термин loss и добавьте термин регуляризации:

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

    Примечание. Похоже, что tf.contrib.layers.apply_regularization реализовано как AddN, более или менее эквивалентно sum(reg_variables).

ответил bluenote10 10 PMpMon, 10 Apr 2017 19:50:23 +030050Monday 2017, 19:50:23
0

Я предоставлю простой правильный ответ, так как я не нашел его. Вам нужно сделать два простых шага, а остальное - с помощью тензорного потока:

  1. Добавьте регуляризаторы при создании переменных или слоев:

    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. Добавьте термин регуляризации при определении потерь:

    loss = ordinary_loss + tf.losses.get_regularization_loss()
    
ответил alyaxey 3 Jpm1000000pmWed, 03 Jan 2018 14:05:58 +030018 2018, 14:05:58
0

Другой вариант сделать это с библиотекой contrib.learn, основанный на Руководство по глубокому MNIST на веб-сайте Tensorflow. Во-первых, предполагая, что вы импортировали соответствующие библиотеки (например, import tensorflow.contrib.layers as layers), вы можете определить сеть отдельным методом:

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 

Затем в основном методе вы можете использовать следующий фрагмент кода:

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)

Чтобы это сработало, вам нужно следовать руководству по MNIST, с которым я ссылался ранее, и импортировать соответствующие библиотеки, но это хорошее упражнение для изучения TensorFlow и легко увидеть, как регуляризация влияет на вывод. Если вы примените регуляризацию в качестве аргумента, вы увидите следующее:

- 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

Обратите внимание, что часть регуляризации дает вам три элемента в зависимости от доступных элементов.

При регуляризации 0, 0,0001, 0,01 и 1,0 я получаю значения точности теста 0,9468, 0,9476, 0,9183 и 0,1135 соответственно, что показывает опасность высоких членов регуляризации.

ответил ComputerScientist 24 Mayam17 2017, 02:55:08
0

Я проверил tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) и tf.losses.get_regularization_loss() с одним l2_regularizer в графе и обнаружил, что они возвращают одно и то же значение. Наблюдая за количеством значения, я думаю, что reg_constant уже имеет смысл для значения, установив параметр tf.contrib.layers.l2_regularizer.

ответил ocean 25 J000000Wednesday18 2018, 11:08:04
0

Некоторые ответы приводят меня в замешательство. Здесь я даю два способа, чтобы это было понятно.

#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 

Затем его можно добавить в общую сумму потерь

ответил user3201329 29 PMpSun, 29 Apr 2018 12:08:24 +030008Sunday 2018, 12:08:24
0
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
ответил Alex-zhai 7 Mayam18 2018, 10:51:32
0

Если у вас есть CNN, вы можете сделать следующее:

В функции модели:

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) 
...

В вашей функции потерь:

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)
ответил tsveti_iko 4 TueEurope/Moscow2018-12-04T14:31:10+03:00Europe/Moscow12bEurope/MoscowTue, 04 Dec 2018 14:31:10 +0300 2018, 14:31:10

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132