看下面的例子
# encoding: utf-8
import numpy as np
import pandas as pd
import random
import math
from keras import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import Adam, RMSprop
from keras.callbacks import LearningRateScheduler
X = [i*0.05 for i in range(100)]
def step_decay(epoch):
initial_lrate = 1.0
drop = 0.5
epochs_drop = 2.0
lrate = initial_lrate * math.pow(drop,
math.floor((1+epoch)/epochs_drop))
return lrate
def build_model():
model = Sequential()
model.add(Dense(32, input_shape=(1,), activation='relu'))
model.add(Dense(1, activation='linear'))
adam = Adam(lr=0.5)
model.compile(loss='mse', optimizer=adam)
return model
model = build_model()
lrate = LearningRateScheduler(step_decay)
callback_list = [lrate]
for ep in range(20):
X_train = np.array(random.sample(X, 10))
y_train = np.sin(X_train)
X_train = np.reshape(X_train, (-1,1))
y_train = np.reshape(y_train, (-1,1))
model.fit(X_train, y_train, batch_size=2, callbacks=callback_list,
epochs=1, verbose=2)
在此示例中,LearningRateSchedule
根本不改变学习率,因为在ep
,epoch=1
的每次迭代中。因此,学习率仅为const(根据step_decay
为1.0)。实际上,不必像示例中那样直接设置epoch
> 1,而是必须执行外部循环,如示例所示,并且在每个循环内部,我只运行了1个时期。 (当我实施深度强化学习而不是监督学习时就是这种情况。)
我的问题是在示例中如何设置指数衰减的学习率,以及如何在ep
的每次迭代中获得学习率。
答案 0 :(得分:2)
您实际上可以将两个参数传递给LearningRateScheduler
。
根据{{3}},调度程序是
以纪元索引作为输入的函数(整数,从 0)和当前学习率,并返回新的学习率作为输出 (浮动)。
因此,基本上,只需将initial_lr
替换为一个函数参数,就像这样:
def step_decay(epoch, lr):
# initial_lrate = 1.0 # no longer needed
drop = 0.5
epochs_drop = 2.0
lrate = lr * math.pow(drop,
math.floor((1+epoch)/epochs_drop))
return lrate
答案 1 :(得分:0)
您实现的实际功能不是指数衰减(如您在标题中所述),而是楼梯功能。
此外,您提到您的学习率在循环内不会改变。的确如此,因为您同时设置了model.fit(..., epochs=1,...)
和epochs_drop = 2.0
。我不确定这是否是您想要的情况。您提供的是一个玩具示例,在这种情况下还不清楚。
我想添加一个更常见的情况,在这种情况下,您不要将for循环与fit()
混合使用,而只是在{{1 }}函数。在这种情况下,您可以使用以下选项:
首先epochs
本身提供了带有预定义优化器的衰减功能。例如,对于您的情况fit()
actual code is:
lr = lr *(1. /(1. + self.decay * K.cast(self.iterations,K.dtype(self.decay))))
也不完全是指数,它与tensorflow's one有所不同。而且,仅当keras
很明显时才使用它。
要遵循指数衰减的张量流约定,您应该实现:
decayed_learning_rate = learning_rate * ^(全局步数/衰减步数)
根据您的需要,您可以选择实现Adam()
子类并在其中定义一个函数(请参见下面的第3个项目符号),也可以使用actually exactly this with some checking的decay > 0.0
:{{1 }}子类,可在每个时期结束时更新学习率。
创建一个子类
Callback
并添加LearningRateScheduler
函数,该函数将使用所有需要的参数初始化实例,并创建一个Callback
变量以跟踪迭代(批次):
class LearningRateExponentialDecay(Callback):
最后,在类中添加实际功能:
__init__()
最酷的部分是,如果您希望上述子类更新每个纪元,则可以使用global_step
,它很好地将纪元作为其签名的参数。这种情况甚至更容易,因为您可以完全跳过全局步骤(除非您想要一种更简单的方法来应用衰减,否则无需立即跟踪它)并在该位置使用 def __init__(self, init_learining_rate, decay_rate, decay_steps):
self.init_learining_rate = init_learining_rate
self.decay_rate = decay_rate
self.decay_steps = decay_steps
self.global_step = 0
。