使用最佳学习率会导致随机猜测的准确性

如何解决使用最佳学习率会导致随机猜测的准确性

我正在通过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}},这就是我得到的:

enter image description here

使用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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-