如何解决使用最佳学习率会导致随机猜测的准确性
我正在通过AurélienGéron的 Scikit-Learn,Keras和TensorFlow 进行动手机器学习,我试图弄清我在做错运动时做错了什么。这是第11章的练习8。我要做的是训练一个神经网络,该神经网络具有CIFAR10数据集上的20个隐藏层(每个100个神经元),激活函数ELU和权重初始化函数He Normal(我知道20个隐藏层的100个神经元是很多,但这就是练习的重点,因此请多多包涵。我必须使用Early Stopping和Nadam Optimizer。
我遇到的问题是我不知道要使用什么学习率。在解决方案笔记本中,作者列出了一堆他尝试过的学习率,并使用了发现的最好的学习率。我对此不满意,因此决定自己尝试找到最佳的学习率。因此,我使用了本书中推荐的一种技术:训练网络一个纪元,在每次迭代中以指数方式提高学习率。然后将损失与学习率的关系作图,查看损失达到最低点的位置,然后选择稍小的学习率(因为这是上限)。
这是我模型中的代码:
model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[32,32,3]))
for _ in range(20):
model.add(keras.layers.Dense(100,activation="elu",kernel_initializer="he_normal"))
model.add(keras.layers.Dense(10,activation="softmax"))
optimizer = keras.optimizers.Nadam(lr=1e-5)
model.compile(loss="sparse_categorical_crossentropy",optimizer=optimizer,metrics=["accuracy"])
(忽略学习率的值,因为我正试图找到合适的值,所以这无关紧要。)
以下是用于找到最佳学习率的代码:
class ExponentialLearningRate(keras.callbacks.Callback):
def __init__(self,factor):
self.factor = factor
self.rates = []
self.losses = []
def on_batch_end(self,batch,logs):
self.rates.append(keras.backend.get_value(self.model.optimizer.lr))
self.losses.append(logs["loss"])
keras.backend.set_value(self.model.optimizer.lr,self.model.optimizer.lr * self.factor)
def find_learning_rate(model,X,y,epochs=1,batch_size=32,min_rate=10**-5,max_rate=10):
init_weights = model.get_weights()
init_lr = keras.backend.get_value(model.optimizer.lr)
iterations = len(X) // batch_size * epochs
factor = np.exp(np.log(max_rate / min_rate) / iterations)
keras.backend.set_value(model.optimizer.lr,min_rate)
exp_lr = ExponentialLearningRate(factor)
history = model.fit(X,epochs = epochs,batch_size = batch_size,callbacks = [exp_lr])
keras.backend.set_value(model.optimizer.lr,init_lr)
model.set_weights(init_weights)
return exp_lr.rates,exp_lr.losses
def plot_lr_vs_losses(rates,losses):
plt.figure(figsize=(10,5))
plt.plot(rates,losses)
plt.gca().set_xscale("log")
plt.hlines(min(losses),min(rates),max(rates))
plt.axis([min(rates),max(rates),min(losses),losses[0] + min(losses) / 2])
plt.xlabel("Learning rate")
plt.ylabel("Loss")
find_learning_rate()
函数在每次迭代中以指数形式增加学习率,从最小学习率10 ^(-5)到最大学习率10。之后,我使用{ {1}},这就是我得到的:
使用function plot_lr_vs_losses()
的学习率看起来不错,对吗?但是,当我以1e-2
的学习率重新编译模型时,模型在训练集和验证集上的准确性均为10%,这就像随机选择一样,因为我们有10个班级。我使用了提前停止功能,所以不能说我让模型训练了太多的时间(我使用了100个)。但是即使在训练期间,该模型也不会学习任何东西,训练集和验证集的准确性始终都在10%左右。
当我使用较小的学习率(解决方案笔记本中作者使用的学习率)时,整个问题消失了。当我使用1e-2
的学习率时,该模型正在学习,并且在验证集上达到了约50%的准确度(这是练习所期望的,与作者获得的准确度相同)。但是,使用该图所示的学习率怎么这么糟糕呢?我在互联网上读了一些书,这种成倍增加学习率的方法似乎已为许多人所用,所以我真的不明白自己做错了什么。
解决方法
您在未知的探索空间上使用启发式搜索方法。没有有关模型/数据特征的更多信息,很难说出出了什么问题。
我首先担心的是对于损失的突然上升到有效无穷大。您在yoru探索空间中的边缘是不是光滑的,这表明较大的空间(包括许多训练时期)具有高度的干扰性边界。在epoch- = 1边界附近的任何学习速度都有可能在较晚的epoch时跌倒穿过悬崖,从而给您带来随机的分类。
您使用的启发式方法基于两个假设。
- 收敛速度与学习率的函数比较平滑 最终精度实际上与学习率无关。 您的模型似乎没有这些特征。
启发式训练仅在一个纪元上进行;在各种学习速率下,收敛模型需要花费多少时间?如果学习率太大,则模型可能会非常缓慢地完成最终收敛,因为它会绕过最佳点。您也可能永远无法以太大的速率接近该点。
如果没有针对那个epoch-1测试映射收敛空间,我们将无法正确地分析问题。但是,您可以 尝试一个相关的实验:也许从10 ^ -4开始,完全训练模型(检测收敛并停止)。重复,每次将LR乘以3。当您进入.0081附近的非收敛状态时,您会感觉不再收敛。
现在,按照您认为合适的那样,将范围细分为[.0027,.0081]。找到可以收敛的上端点后,就可以用来指导最终搜索以获得最佳学习率。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。