¿Cómo establecer la tasa de aprendizaje en capas en Tensorflow?


Me pregunto si hay una manera de que pueda usar diferentes tasas de aprendizaje para diferentes capas como lo que está en Caffe. Estoy tratando de modificar un modelo pre-entrenado y usarlo para otras tareas. Lo que quiero es acelerar el entrenamiento para nuevas capas agregadas y mantener las capas entrenadas a una tasa de aprendizaje baja para evitar que se distorsionen. por ejemplo, tengo un modelo preentrenado de 5 capas conv. Ahora agrego una nueva capa conv y la afino. Las primeras 5 capas tendrían una tasa de aprendizaje de 0.00001 y el último tendría 0.001. ¿Alguna idea de cómo lograrlo?

Author: Tong Shen, 2016-01-22

5 answers

Se puede lograr fácilmente con 2 optimizadores:

var_list1 = [variables from first 5 layers]
var_list2 = [the rest of variables]
train_op1 = GradientDescentOptimizer(0.00001).minimize(loss, var_list=var_list1)
train_op2 = GradientDescentOptimizer(0.0001).minimize(loss, var_list=var_list2)
train_op = tf.group(train_op1, train_op2)

Una desventaja de esta implementación es que calcula tf.degradado(.) dos veces dentro de los optimizadores y por lo tanto podría no ser óptimo en términos de velocidad de ejecución. Esto se puede mitigar llamando explícitamente a tf.degradado(.), dividiendo la lista en 2 y pasando los gradientes correspondientes a ambos optimizadores.

Pregunta relacionada: Mantener constantes las variables durante el optimizador

EDITAR: Añadido más implementación eficiente pero más larga:

var_list1 = [variables from first 5 layers]
var_list2 = [the rest of variables]
opt1 = tf.train.GradientDescentOptimizer(0.00001)
opt2 = tf.train.GradientDescentOptimizer(0.0001)
grads = tf.gradients(loss, var_list1 + var_list2)
grads1 = grads[:len(var_list1)]
grads2 = grads[len(var_list1):]
tran_op1 = opt1.apply_gradients(zip(grads1, var_list1))
train_op2 = opt2.apply_gradients(zip(grads2, var_list2))
train_op = tf.group(train_op1, train_op2)

Puede usar tf.trainable_variables() para obtener todas las variables de entrenamiento y decidir seleccionar entre ellas. La diferencia es que en la primera implementación tf.gradients(.) se llama dos veces dentro de los optimizadores. Esto puede causar que se ejecuten algunas operaciones redundantes (por ejemplo, los gradientes en la primera capa pueden reutilizar algunos cálculos para los gradientes de las siguientes capas).

 67
Author: Rafał Józefowicz,
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 11:47:05

Actualización Jan 22 : receta a continuación es solo una buena idea para GradientDescentOptimizer, otros optimizadores que mantienen un promedio de ejecución aplicarán la tasa de aprendizaje antes de la actualización del parámetro, por lo que receta a continuación no afectará esa parte de la ecuación

Además del enfoque de Rafal, podrías usar compute_gradients, apply_gradients interfaz de Optimizer. Por ejemplo, aquí hay una red de juguetes donde uso 2 veces la tasa de aprendizaje para el segundo parámetro

x = tf.Variable(tf.ones([]))
y = tf.Variable(tf.zeros([]))
loss = tf.square(x-y)
global_step = tf.Variable(0, name="global_step", trainable=False)

opt = tf.GradientDescentOptimizer(learning_rate=0.1)
grads_and_vars = opt.compute_gradients(loss, [x, y])
ygrad, _ = grads_and_vars[1]
train_op = opt.apply_gradients([grads_and_vars[0], (ygrad*2, y)], global_step=global_step)

init_op = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init_op)
for i in range(5):
  sess.run([train_op, loss, global_step])
  print sess.run([x, y])

Deberías ver

[0.80000001, 0.40000001]
[0.72000003, 0.56]
[0.68800002, 0.62400001]
[0.67520005, 0.64960003]
[0.67008007, 0.65984005]
 7
Author: Yaroslav Bulatov,
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-01-23 01:19:25

Tensorflow 1.7 introdujo tf.custom_gradient que simplifica enormemente la configuración de multiplicadores de velocidad de aprendizaje, de una manera que ahora es compatible con cualquier optimizador, incluidos los que acumulan estadísticas de gradiente. Por ejemplo,

import tensorflow as tf

def lr_mult(alpha):
  @tf.custom_gradient
  def _lr_mult(x):
    def grad(dy):
      return dy * alpha * tf.ones_like(x)
    return x, grad
  return _lr_mult

x0 = tf.Variable(1.)
x1 = tf.Variable(1.)
loss = tf.square(x0) + tf.square(lr_mult(0.1)(x1))

step = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(loss)

sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
tf.local_variables_initializer().run()

for _ in range(5):
  sess.run([step])
  print(sess.run([x0, x1, loss]))
 5
Author: P-Gn,
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-08-08 08:00:05

Recopilar multiplicadores de tasa de aprendizaje para cada variable como:

self.lr_multipliers[var.op.name] = lr_mult

Y luego aplicarlos durante antes de aplicar los gradientes como:

def _train_op(self):
  tf.scalar_summary('learning_rate', self._lr_placeholder)
  opt = tf.train.GradientDescentOptimizer(self._lr_placeholder)
  grads_and_vars = opt.compute_gradients(self._loss)
  grads_and_vars_mult = []
  for grad, var in grads_and_vars:
    grad *= self._network.lr_multipliers[var.op.name]
    grads_and_vars_mult.append((grad, var))
    tf.histogram_summary('variables/' + var.op.name, var)
    tf.histogram_summary('gradients/' + var.op.name, grad)
  return opt.apply_gradients(grads_and_vars_mult)

Puedes encontrar el ejemplo completo aquí.

 4
Author: Sergey Demyanov,
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-06-15 02:51:05

Las primeras 5 capas tendrían una tasa de aprendizaje de 0.00001 y la última tendría 0.001. ¿Alguna idea de cómo lograrlo?

Hay una manera fácil de hacerlo usando tf.stop_gradient. Aquí hay un ejemplo con 3 capas:

x = layer1(input)
x = layer2(x)
output = layer3(x)

Puede reducir su gradiente en las dos primeras capas en una proporción de 1/100:

x = layer1(input)
x = layer2(x)
x = 1/100*x + (1-1/100)*tf.stop_gradient(x)
output = layer3(x)

En la capa 2, el "flujo" se divide en dos ramas: una que tiene una contribución de 1/100 calcula su gradiente regularmente pero con un gradiente la magnitud reducida en una proporción de 1/100, la otra rama proporciona el "flujo" restante sin contribuir al gradiente debido al tf.stop_gradient operador. Como resultado, si utiliza una tasa de aprendizaje de 0.001 en su optimizador de modelos, las dos primeras capas tendrán virtualmente una tasa de aprendizaje de 0.00001.

 0
Author: Nicolas Pinchaud,
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-11-27 19:11:42