Comment définir le taux d'apprentissage par niveaux dans Tensorflow?

je me demande s'il y a un moyen que je puisse utiliser un taux d'apprentissage différent pour différentes couches comme ce qui est dans Caffe. J'essaie de modifier un modèle pré-formé et de l'utiliser pour d'autres tâches. Ce que je veux est d'accélérer la formation de nouvelles couches et de garder la formation de couches à faible taux d'apprentissage afin de les empêcher d'être déformée. par exemple, j'ai un 5-conv-couche pré-formés modèle. Maintenant, j'ajoute une nouvelle couche conv et je l'ajuste. Les 5 premières couches aurait apprentissage taux de 0.00001 et le dernier aurait 0.001. Une idée de comment réaliser cela?

41
demandé sur Tong Shen 2016-01-22 14:22:10

5 réponses

Il peut être réalisé assez facilement avec 2 optimiseurs:

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)

un inconvénient de cette implémentation est qu'elle calcule tf.dégradé.() deux fois à l'intérieur des optimiseurs et donc il pourrait ne pas être optimal en termes de vitesse d'exécution. Ceci peut être atténué en appelant explicitement tf.dégradé.(), en divisant la liste en 2 et en passant les gradients correspondants aux deux optimiseurs.

question connexe: variables de détention constante lors de l'optimisation

modifier: ajouté une mise en œuvre plus efficace mais plus longue:

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)

vous pouvez utiliser tf.trainable_variables() pour obtenir toutes les variables de formation et décider de choisir parmi elles. La différence est que dans la première implémentation tf.gradients(.) est appelé deux fois à l'intérieur des optimiseurs. Cela peut entraîner l'exécution de certaines opérations redondantes (par exemple, les gradients de la première couche peuvent réutiliser certains calculs pour les gradients de la couches suivantes).

67
répondu Rafał Józefowicz 2017-05-23 11:47:05

Update Jan 22 : la recette ci-dessous est seulement une bonne idée pour GradientDescentOptimizer , d'autres optimiseurs qui maintiennent une moyenne courante appliqueront le taux d'apprentissage avant la mise à jour du paramètre, donc la recette ci-dessous n'affectera pas cette partie de l'équation

en plus de L'approche de Rafal, vous pouvez utiliser compute_gradients , apply_gradients interface de Optimizer . Par exemple, voici un réseau de jouets où j'utilise 2x le taux d'apprentissage pour le deuxième paramètre

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

Vous devriez voir

[0.80000001, 0.40000001]
[0.72000003, 0.56]
[0.68800002, 0.62400001]
[0.67520005, 0.64960003]
[0.67008007, 0.65984005]
7
répondu Yaroslav Bulatov 2016-01-23 01:19:25

Tensorflow 1.7 introduit tf.custom_gradient qui simplifie grandement le réglage des multiplicateurs de taux d'apprentissage, d'une manière qui est maintenant compatible avec n'importe quel optimiseur, y compris ceux accumulant des statistiques de gradient. Par exemple,

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
répondu P-Gn 2018-08-08 08:00:05

collecter des multiplicateurs de taux d'apprentissage pour chaque variable comme:

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

et ensuite les appliquer pendant avant d'appliquer les gradients comme:

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)

vous pouvez trouver l'exemple entier ici .

4
répondu Sergey Demyanov 2016-06-15 02:51:05

les cinq premières couches auraient un taux d'apprentissage de 0,00001 et la dernière aurait 0,001. Une idée de comment réaliser cela?

il y a un moyen facile de le faire en utilisant tf.stop_gradient. Voici un exemple avec 3 couches:

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

vous pouvez rétrécir votre gradient dans les deux premières couches par un rapport de 1/100:

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

sur le Layer 2, le "flux" est divisé en deux branches: une qui a une contribution de 1/100 calcule son gradient régulièrement mais avec une magnitude de gradient rétrécie par une proportion de 1/100, l'autre branche fournit le "débit" restant sans contribuer au gradient à cause du tf.stop_gradient de l'opérateur. Par conséquent, si vous utilisez un taux d'apprentissage de 0,001 sur votre modèle optimizer, les deux premières couches auront virtuellement un taux d'apprentissage de 0,00001.

0
répondu Nicolas Pinchaud 2017-11-27 19:11:42