Как добавить регуляризации в TensorFlow?
Я нашел во многих доступных коде нейронной сети, реализованном с использованием TensorFlow, что термины регуляризации часто реализуются путем ручного добавления дополнительного термина к значению потери.
мои вопросы:
есть ли более элегантный или рекомендуемый способ регуляризации, чем делать это вручную?
Я также считаю, что
get_variable
есть аргументregularizer
. Как его использовать? По моим наблюдениям, если мы пройдем регуляризатор к нему (например,tf.contrib.layers.l2_regularizer
, тензор, представляющий регуляризованный член, будет вычислен и добавлен в коллекцию графов с именемtf.GraphKeys.REGULARIZATOIN_LOSSES
. Будет ли эта коллекция автоматически использоваться TensorFlow (например, используется оптимизаторами при обучении)? Или предполагается, что я должен использовать эту коллекцию сам?
7 ответов
как вы говорите во втором пункте, с помощью 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)
надеюсь, что это поможет!
некоторые аспекты существующего ответа были мне не сразу понятны, поэтому вот пошаговое руководство:
-
определите регуляризатор. Здесь можно установить константу регуляризации, например:
regularizer = tf.contrib.layers.l2_regularizer(scale=0.1)
-
создание переменных через:
weights = tf.get_variable( name="weights", regularizer=regularizer, ... )
эквивалентно, переменные могут быть созданы через обычный
weights = tf.Variable(...)
Конструктор, за которым следуетtf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES, weights)
. -
определить
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)
.
еще один вариант сделать это с помощью 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, соответственно, показывая опасности максимума условия регуляризации.
Я дам простой правильный ответ, так как я его не нашел. Вам нужно два простых шага, остальное делает tensorflow magic:
-
добавить регуляризаторы при создании переменных или слоев:
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))
-
добавить термин регуляризации при определении потерь:
loss = ordinary_loss + tf.losses.get_regularization_loss()
Я проверял tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
и tf.losses.get_regularization_loss()
С l2_regularizer
на графике и обнаружил, что они возвращают одно и то же значение. Наблюдая за количеством значения, я думаю, reg_constant уже имеет смысл для значения, установив параметр tf.contrib.layers.l2_regularizer
.
некоторые ответы делают меня более запутанным.Здесь я даю два метода, чтобы сделать это ясно.
#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
затем его можно добавить в общую потерю
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