Ton*_*hen 46 python deep-learning tensorflow
我想知道是否有一种方法可以为不同的层使用不同的学习率,就像Caffe中的那样.我正在尝试修改预先训练的模型并将其用于其他任务.我想要的是加快新增加的层的训练,并使训练好的层保持低学习率,以防止它们被扭曲.例如,我有一个5-conv层预训练模型.现在我添加一个新的转换层并对其进行微调.前5层的学习率为0.00001,最后一层的学习率为0.001.知道怎么做到这一点?
Raf*_*icz 81
使用2个优化器可以很容易地实现:
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)
Run Code Online (Sandbox Code Playgroud)
这种实现的一个缺点是它在优化器内部计算两次tf.gradients(.),因此在执行速度方面可能不是最佳的.这可以通过显式调用tf.gradients(.),将列表拆分为2并将相应的渐变传递给两个优化器来缓解.
相关问题:在优化器期间保持变量不变
编辑:添加更有效但更长的实现:
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)
Run Code Online (Sandbox Code Playgroud)
您可以使用tf.trainable_variables()
获取所有训练变量并决定从中进行选择.不同之处在于第一个实现tf.gradients(.)
在优化器内部被调用两次.这可能导致执行一些冗余操作(例如,第一层上的梯度可以重用一些计算用于后续层的梯度).
1月22日更新:下面的配方只是一个好主意GradientDescentOptimizer
,保持运行平均值的其他优化器将在参数更新之前应用学习速率,因此下面的配方不会影响等式的那一部分
除了Rafal的方法,你可以使用compute_gradients
,apply_gradients
界面Optimizer
.例如,这是一个玩具网络,我使用2倍于第二个参数的学习率
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])
Run Code Online (Sandbox Code Playgroud)
你应该看到
[0.80000001, 0.40000001]
[0.72000003, 0.56]
[0.68800002, 0.62400001]
[0.67520005, 0.64960003]
[0.67008007, 0.65984005]
Run Code Online (Sandbox Code Playgroud)
Tensorflow 1.7引入tf.custom_gradient
了大大简化设置学习速率乘数的方法,现在与任何优化器兼容,包括那些累积梯度统计数据.例如,
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]))
Run Code Online (Sandbox Code Playgroud)
收集每个变量的学习率乘数,例如:
self.lr_multipliers[var.op.name] = lr_mult
Run Code Online (Sandbox Code Playgroud)
然后在应用渐变之前应用它们,例如:
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)
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到整个示例。
归档时间: |
|
查看次数: |
22983 次 |
最近记录: |