前言:
在各种论文中,我见到过最多的优化器就是SGD,虽然Adam,Nadam很潮,优点很多,但是我也不知道为啥,那些很优秀的论文总是喜欢用SGD,或许是因为SGD的学习率和和decay可‘手动’调节的缘故吧,SGD的学习率衰减策略有很多,接下来就讲解一个各个衰减策略,以及poly衰减策略的实现,另一方面是网上基本上是没有Keras上实现poly的代码,经过我一个下午的摸索,终于实现了。
SGD优化策略:
随机梯度下降法,支持动量参数,支持学习衰减率,支持Nesterov动量。
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
参数:
- lr:大于0的浮点数,学习率
- momentum:大于0的浮点数,动量参数
- decay:大于0的浮点数,每次更新后的学习率衰减值
- nesterov:布尔值,确定是否使用Nesterov动量
其中这个decay是很值得玩味的
默认decay设置
Keras 已经内置了一个基于时间的学习速率调整表,并通过上述参数中的 decay
来实现,学习速率的调整公式如下:
LearningRate = LearningRate * 1/(1 + decay * iteration)
当我们初始化参数为:
LearningRate = 0.1
decay = 0.001
100 个 iteration后学习速率将变为 0 ,其变化曲线如下:
上面这个decay是在SGD函数里面的decay参数里直接设置就可以使用的,但是直接设置的只有这一种,如果你想得到其他种类的学习率下降模式,你要自己写 LearningRateScheduler 这个回调函数的接口,具体如下
Drop-Based Learning Rate Schedule
这个学习率下降方式是在训练过程中,以台阶的方式下降的:
通常,通过将学习速率降低每个固定数量的epoch的一半来实现该方法。 例如,我们具有0.1的初始学习率并且每10个epoch将其降低0.5。 前10个训练时期将使用0.1的值,在接下来的10个时期中将使用0.05的学习率,依此类推。
根据这个曲线,学习率函数可以这样定义:
LearningRate = InitialLearningRate * DropRate^floor(Epoch / EpochDrop)
具体函数如下:
def step_decay(epoch):
initial_lrate = 0.1
drop = 0.5
epochs_drop = 10.0
lrate = initial_lrate * math.pow(drop, math.floor((1+epoch)/epochs_drop))
return lrate
应用这个学习率函数:
sgd = SGD(lr=0.0, momentum=0.9, decay=0.0, nesterov=False)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
# learning schedule callback
lrate = LearningRateScheduler(step_decay)
callbacks_list = [lrate]
# Fit the model
model.fit(X, Y, validation_split=0.33, epochs=50, batch_size=28, callbacks=callbacks_list, verbose=2)
请注意:LearningRateScheduler()这个回调函数接收的是一个以epoch为入口参数,返回的是一个float型的学习率的函数
Poly Learning Rate Policy
学习率下降公式:
LearningRate = InitialLearningRate*(1 - iter/max_iter) ^ (power)
曲线如下:
LearningRateScheduler()回调函数接口:
def poly_decay(epoch):
# initialize the maximum number of epochs, base learning rate,
# and power of the polynomial
maxEpochs = Epochs
step_each_epoch=400#根据自己的情况设置
baseLR = 0.01
power = 0.9
ite = K.get_value(model.optimizer.iterations)
# compute the new learning rate based on polynomial decay
alpha = baseLR*((1 - (ite / float(maxEpochs*step_each_epoch)))**power)
# return the new learning rate
return alpha
应用:
sgd = SGD(lr=0.01, momentum=0.9, decay=0.0, nesterov=False)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
# learning schedule callback
lrate = LearningRateScheduler(poly_decay)
callbacks_list = [lrate]
# Fit the model
model.fit(X, Y, validation_split=0.33, epochs=50, batch_size=28, callbacks=callbacks_list, verbose=2)