step-by-step: 夕小瑶版神经网络调参指南(上)

距离上一篇文章已经过去好久好久好久啦。闭关几个月后,其实早有继续码文章的打算,先后写了一下核函数与神经网络的一些思考、文本预处理tricks、不均衡文本分类问题、多标签分类问题、tensorflow常用tricks、噪声对比估算与负采样等文章,结果全都半途而废,写了一半然后各种原因丢掉了就不想再接着写。结果电脑里稿子攒了好多,却让订阅号空了这么久。今天终于下定决心必须要码一篇了,下午临时决定写一篇神经网络调参的文章,嗯,就是这一篇啦。

序言

虽然现在仅仅靠调参已经在深度学习领域不是香饽饽了,但是如果连参数都不会调,那可能连肉汤都喝不到的。毕竟你有再好的idea,也需要有一个漂亮的实验结果去支撑的对不对,参数调不好,千里马也容易被当成骡子。

 

说到调参,也不得不吐槽现在行业里论文复现难的问题。小夕曾经非常好奇AAAI2018某送审文章的性能,于是完全按照论文里的设定去做了复现,发现跟与论文中的结果足足差了4个百分点!更神奇的是我发现按照该论文的设定,模型远不足以拟合数据集 ╮( ̄▽ ̄"")╭ 最后实在get不到论文里的trick了,小夕就放开了自己调!结果最后调的比该论文里的结果还高了0.5个点,着实比较尴尬。

我们不能说某些顶会论文数据有问题,但是可以确信的是显式或隐式的超参数很可能大大的影响实验结果,这个超参数或许来自数据预处理,或许来自优化算法,或许来自模型本身,甚至有时候是来自输出层的推理阶段。

调参前的准备

好啦,回到正题上。在调参之前,小夕强烈建议在代码里完成下面几件事:

  1. 可视化训练过程中每个step(batch)的loss。如果是分类任务,可以顺便可视化出每个batch的准确率(不均衡数据可视化F1-score)。

  2. 将训练日志在打印到屏幕上的同时也写入到本地磁盘。如果能实时同步写入那更好了(在python中可以用logging模块可以轻松实现。一个handler输出到屏幕,再设置一个handler输出到磁盘即可)。

  3. 借助tensorflow里的FLAGS模块或者python-fire工具将你的训练脚本封装成命令行工具。

  4. 代码中完成tensorboard等训练过程可视化环境的配置,最少要可视化出训练loss曲线。

  5. 如果使用tensorflow,记得设置GPU内存动态增长(除非你只有一个GPU并且你确信一个训练任务会消耗GPU的一大半显存)

 

另外,初始调参阶段记得关闭L2、Dropout等用来调高模型泛化能力的超参数呐,它们很可能极大的影响loss曲线,干扰你的重要超参数的选取。然后根据自己的任务的量级,预估一个合理的batch size(一般来说64是个不错的初始点。数据集不均衡的话建议使用更大一点的值,数据集不大模型又不是太小的情况下建议使用更小一些的值)。如果对网络参数的随机初始化策略缺乏经验知识(知识来源于相关任务的论文实验细节或开源项目等),可以使用He方法[1](使用ReLU激活时)或Xavier方法[2]来进行网络参数初始化。

阶段1:learning rate和num steps

这个阶段是最容易的,打开tensorboard,按照指数规律设置几组可能的学习率,小夕一般设置如下六组[1, 0.1, 0.01, 0.001, 0.0001, 0.00001]。

 

如果你的GPU比较多,你还可以在几个大概率学习率附近多插几个值,比如小夕一般喜欢再插上[0.03, 0.05, 0.003, 0.005, 0.007, 0.0005]这几个值(最起码在做文本分类任务时经常撞到不错的结果哦)。

 

当这些任务跑完时,就可以去tensorboard里挑选最优学习率啦。选择原则也很简单,选择那条下降的又快又深的曲线所对应的学习率即可,如下图,选择粉色那条曲线:

 

选择好学习率后,顺便再观察一下这条曲线,选择一个差不多已经收敛的step作为我们的训练总steps(如果数据集规模小的话也可以换算成epoch次数)。如图

可以看到,我们的模型在迭代到4K步的时候就基本收敛了,保险起见我们可以选择6K来作为我们训练的总num_steps(毕竟后面改动的超参数可能使收敛延后嘛)。

 

细节:

如果GPU有限并且任务对显存的消耗没有太大,那么可以同时在一个GPU里挂上多组训练任务(这时每组任务的计算速度会有损耗,但是完成全部任务所消耗的总时间大大减少了)。小夕一般先随便设个学习率跑一下,确定一下每个任务大体消耗的显存,然后在shell脚本里将这若干个任务塞进GPU里并行跑(shell脚本里直接用&扔进后台即可)。当然,如果代码里用到了时间戳,可以给时间戳加个随机噪声或者在shell脚本里为任务之间加上一定的时间间隔,免得训练任务的时间戳发生碰撞。

 

买不起GPU版:

曾经有一段时间小夕只有一个可以用的GPU,然而任务规模又大到每次实验要占用一大半的GPU显存且要跑一天半,然而时间又特别紧,来不及像上面一样跑十几次实验去选个学习率。那怎么办呢?

 

小夕get到一个trick,就是在代码里计算出来每次更新时的梯度更新向量的模与当前参数向量的模的比值。如果这个比值在量级附近的话说明学习率还可以,如果数量级太小,则网络更新不动,需要增大学习率。数量级太大则每次更新对网络的修改太大,网络很容易发生不稳定,需要降低学习率。这样基本跑几个batch就能估算一次学习率,很快就能get到一个凑合使用的学习率。

 

阶段2:batch size和momentum

带着第一阶段得到的超参数,我们来到了第二阶段。

 

如果我们使用的是Adam这种“考虑周全”的优化器的话,动量项momentum这类优化器的超参数就基本省了。然而,不仅是小夕的经验,业界广泛的经验就是Adam找到的最优点往往不如精调超参的SGD找到的超参数质量高。因此如果你想要追求更加极限的性能的话,momentum还是要会调的哦。

 

momentum一方面可以加速模型的收敛(减少迭代步数),另一方面还可以带领模型逃离差劲的局部最优点(没理解的快回去看看momentum SGD的公式)。而batch size参数似乎也能带来类似的作用——batch size越小,噪声越大,越容易逃离局部最优点,同时这时对梯度的估计不准确,导致需要更多的迭代步数。因此小夕一般将这两个参数一起调。

 

两个参数同时调的时候可以使用传统的网格搜索,也可以使用大牛们提倡的随机搜索[3]。小夕觉得嘛,GPU多又时间充裕的话就网格搜索,否则就随机搜索啦。反正两个超参数时使用网格搜索也不是让人那么无法接受。还不熟悉这两种策略的同学可以去Ng在coursera开的深度学习课上补补哦,“超参数调节”这几节课讲的很清晰而且貌似是公开的。

 

另外,如果使用网格搜索并且搜索范围小的话小夕一般直接在shell脚本里偷懒解决:

 

另外,由于这两个超参数可能涉及到模型的泛化能力,因此记得在监控loss曲线的同时也要监控开发集准确率哦。如果两组实验的loss曲线的形状都很好,这时就可以根据开发集准确率来做取舍了(一般不会出现loss曲线形状很差但是开发集准确率超好的情况)。

 

另外,还要记得!这一阶段结束后,可能最优的loss曲线会发生很大的变化,可能第一阶段我们确定的num_steps在这一阶段已经变得过分冗余了,那么我们在这一阶段结束后要记得把尾巴剪短一些哦(即减少num_steps,减少的依据跟以前一样)。当然如果batch size低了很多,有可能之前的num_steps不足以充分训练了,那么要记得增加步数啦。

阶段3:学习率衰减策略

 

相比较前面几个超参数,学习率衰减策略就比较神奇了。有时你会发现这个超参数好像没有什么用,有时却会发现它像开了挂一样让你看似已经收敛的网络更进一层,带来更低的训练loss和更高的开发集准确率。

这个其实也很容易理解啦,如果你的模型在收敛时走到了“高原地带”,这时其实你衰减学习率不会带来太大改观。而如果收敛时在“峡谷边缘”来回跳跃,这时你衰减学习率就可能一步跨下峡谷,发现新大陆!当然啦,这也只能是我们的YY,在手头任务中谁也不清楚这几百万几千万维度的空间里的地形。所以不妨使用一个简单有效的学习率衰减策略简单一调,有用就继续精调,没用就算啦。

 

经典的学习率衰减策略要同时考虑4个东西:衰减开始的时机、衰减量级(线性衰减or指数衰减)、衰减速率以及衰减的周期。

 

还记得我们上个阶段得到的开发集准确率曲线吗?没错!这条曲线的低谷附近就是开始衰减的好时机!

衰减时机很好确定,例如上面这种状态,最高开发集准确率在3000左右,那么我们不妨从2700左右开始衰减学习率。

衰减量级来说,貌似大家用指数衰减更多一点。不过呢,对于指数衰减来说,衰减因子调节起来较为敏感,一旦衰减因子太小,则model往往还没有训练够呢就衰减没了。因子设置太大的话迭代好久学习率还是下不去,导致开发集的性能提升不大。考虑这些的同时还要把握好衰减的间隔(也就是每多少个steps衰减一次),如果间隔过小,则开发集准确率的波峰附近相比无衰减时更平缓,如果间隔过大,容易发现除了第一次衰减,后面的衰减都不会带来什么收益。不过,最最起码的一个设计原则是,在到达原先的最高开发集准确率点的那个step时,最少衰减为初始学习率的一半才行(除非你的衰减间隔真的很短)。

 

是不是感觉超级麻烦哇,为了一个学习率衰减要去考虑和计算这么多东西,感觉好麻烦哦,所以小夕个人更喜欢用下面这种懒办法。

 

这种方法是从fasttext源码里学到的,实验了一下发现还蛮好用的就一直用了下来。首先,开始衰减的点不用算,直接从第一步起就开始线性衰减。然后假如总迭代步数为5K,学习率为0.01,那么我们就可以算一下每一步学习率的衰减量为

 

粗略算一下发现这时到达第3000步时的学习率为0.006,好像还蛮合理的诶。这样在最后一步时,学习率也恰好衰减到0。

在这个方案里,我们可以每个step都重新计算学习率,但是为了防止某些情况浮点下溢以及额外的计算开销(虽然可以忽略),往往还是设置一个衰减间隔,比如每100steps衰减一次。相比经典策略,这时的衰减间隔就不那么敏感啦,放心大胆的去设置。

使用这种懒办法基本没有引入任何难调的超参数,只要你在第二阶段的num_steps设置的合理,这一阶段的懒版学习率衰减就能往往取得不错的效果。

当然,如果在当前任务中发现这个懒办法也没带来多少收益,那这个任务可能真是地形相对平坦,对学习率衰减不太敏感,这时小夕一般不会考虑精调衰减策略。反之,如果发现这种懒办法都带来了明显的收益,那么仔细对比一下衰减策略下的开发集曲线和无衰减策略的开发集曲线,如果发现波峰后移的厉害,那可能衰减的太快了,尝试推后衰减时机。不过,既然有明显收益,那这时按照经典衰减策略再精调往往也不亏啦。

剩下的超参数要怎么调呢?坐等小夕的下一篇文章咯( ̄∇ ̄)

[1] Xavier Glorot and Yoshua Bengio. 2010. Understanding the difficulty of training deep feedforward neural networks. In Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics, volume 9 of Proceedings of Machine Learning Research, pages 249–256, Chia Laguna Resort, Sardinia, Italy. PMLR.

[2] Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. 2015. Delving deep into rectifiers: Surpassing human-level performance on imagenet classification. CoRR, abs/1502.01852.

[3] Bergstra J, Bengio Y. Random search for hyper-parameter optimization[J]. Journal of Machine Learning Research, 2012, 13(Feb): 281-305.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/481123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌发布端到端AI平台,还有用于视频和表格的AutoML、文档理解API等多款工具

谷歌又有了大动作。在大洋彼岸的谷歌Cloud Next conference大会上,谷歌一口气发布了多款AI新品和工具,主要包括: 端到端的AI平台 用于处理视频和表格数据的AutoML Tables和AutoML Video 文档理解API 联络中心AI 视觉产品搜索 对于开发者…

跨性别,你所不知道的事

今晚原计划在订阅号里推送南溪妹子前几天录制的跨性别科普视频,没想到今天收到南溪的私信,说不做科普了,还是算了吧。急忙去了解了一下原因 (http://www.zhihu.com/pin/963101597957644288) ,才知道南溪因这段视频所遭受的无故攻击…

文本分类问题不需要ResNet?小夕解析DPCNN设计原理(上)

历史回顾回顾一下图像和文本的发展史,似乎这就是一场你追我赶的游戏。在上一阶段的斗争中,朴素贝叶斯、最大熵、条件随机场这些理论完备的统计机器学习模型使得文本分类、中文分词、NER等诸多自然语言处理问题取得了差强人意(释义&#xff1a…

【Tensorflow】TensorFlow的嵌入layer和多层layer

计算图中的操作 # python 3.6 import tensorflow as tf import numpy as npsess tf.Session()# 将张量和占位符对象组成一个计算图,创建一个简单的分类器# 一、计算图中的操作 # 1. 声明张量和占位符,创建numpy数组,传入计算图操作 x_vals …

文本分类问题不需要ResNet?小夕解析DPCNN设计原理(下)

哎呀呀,说好的不拖稿的又拖了两天T_T,小夕过一阵子分享给你们这两天的开心事哦。后台催稿调参系列的小伙伴们不要急,下一篇就是第二篇调参文啦。好啦,接着上一篇文章,直接搬来DPCNN、ShallowCNN、ResNet的对比图。从图…

注意力机制-深度学习中的注意力机制+注意力机制在自然语言处理中的应用

1 深度学习中的注意力机制 https://mp.weixin.qq.com/s?__bizMzA4Mzc0NjkwNA&mid2650783542&idx1&sn3846652d54d48e315e31b59507e34e9e&chksm87fad601b08d5f17f41b27bb21829ed2c2e511cf2049ba6f5c7244c6e4e1bd7144715faa8f67&mpshare1&scene1&src…

【TensorFlow】常用的损失函数及其TensorFlow实现

1 损失函数 定义:将随机事件或其有关随机变量的取值映射为非负实数以表示该随机事件的“风险”或“损失”的函数。 应用:作为学习准则与优化问题相联系,即通过最小化损失函数求解和评估模型。 分类:回归问题、分类问题 2 回归问…

从经典文本分类模型TextCNN到深度模型DPCNN

如今深度学习已经成为NLP领域的标配技术,在图像中大为成功的卷积神经网络(CNN)也开始广泛渗透到文本分类、机器翻译、机器阅读等NLP任务中。但是,在ACL2017以前,word-level的文本分类模型(以单词为语义单位…

从特征分解到协方差矩阵:详细剖析和实现PCA算法

从特征分解到协方差矩阵:详细剖析和实现PCA算法本文先简要明了地介绍了特征向量和其与矩阵的关系,然后再以其为基础解释协方差矩阵和主成分分析法的基本概念,最后我们结合协方差矩阵和主成分分析法实现数据降维。本文不仅仅是从理论上阐述各种…

NLP中常用文本分类模型汇总

如今深度学习已经成为NLP领域的标配技术,在图像中大为成功的卷积神经网络(CNN)也开始广泛渗透到文本分类、机器翻译、机器阅读等NLP任务中。但是,在ACL2017以前,word-level的文本分类模型(以单词为语义单位…

【TensorFlow】随机训练和批训练的比较与实现

一、随机训练和批训练 随机训练:一次随机抽样训练数据和目标数据对完成训练。批训练:一次大批量训练取平均损失来进行梯度计算,批量训练大小可以一次上扩到整个数据集。批训练和随机训练的差异:优化器方法和收敛的不同批训练的难…

「小公式」平均数与级数

喵喵喵,小夕最近准备复习一下数学和基础算法,所以可能会推送或者附带推送点数学和基础算法的小文章。说不定哪天就用(考)到了呢( ̄∇ ̄)注意哦,与头条位的文章推送不同,「小公式」和「…

最新出炉-阿里 2020届算法工程师-自然语言处理(实习生)以及补充:快递最短路径

问题2感觉跟下面的分苹果类似; 问题 G: 分梨 题目描述 zzq非常喜欢吃梨,有一天他得到了ACMCLUB送给他的一筐梨子。由于他比较仗义,就打算把梨子分给好朋友们吃。现在他要把M个梨子放到N个盘子里面(我们允许有的盘子为空&#xff0…

如何匹配两段文本的语义?

喵喵喵,好久不见啦。首先很抱歉大家期待的调参手册(下)迟迟没有出稿,最近两个月连着赶了4个DDL,整个人都不好了。最近几天终于有时间赶一下未完成的稿子了。在赶DDL的时候夹着写了这篇文章,就先发布这一篇吧…

【TensorFlow】实现简单的鸢尾花分类器

代码实现及说明 # python 3.6 # TensorFlow实现简单的鸢尾花分类器 import matplotlib.pyplot as plt import tensorflow as tf import numpy as np from sklearn import datasetssess tf.Session()#导入数据 iris datasets.load_iris() # 是否是山鸢尾 0/1 binary_target …

偏差-方差全面解释

偏差(Bias)与方差(Variance) 目录: 为什么会有偏差和方差?偏差、方差、噪声是什么?泛化误差、偏差和方差的关系?用图形解释偏差和方差。偏差、方差窘境。偏差、方差与过拟合、欠拟合…

「小算法」回文数与数值合法性检验

喵喵喵,小夕最近准备复习一下数学和基础算法,尽量每篇推送下面会附带点数学和基础算法的小文章。说不定哪天就用(考)到了呢( ̄∇ ̄)注意哦,与头条位的文章推送不同,「小公式」和「小算…

【TensorFlow】实现、训练并评估简单的回归模型和分类模型

1 回归模型 回归算法模型用来预测连续数值型,其目标不是分类值而是数字。为了评估这些回归预测值是否与实际目标相符,我们需要度量两者间的距离,打印训练过程中的损失,最终评估模型损失。 这里使用的例子是从均值为1、标准差为0…

史上最通熟易懂的检索式聊天机器人讲解

喵喵喵,一不小心又匿了三个月,突然诈尸害不害怕( ̄∇ ̄) 小夕从7月份开始收到第一场面试邀请,到9月初基本结束了校招(面够了面够了T_T),深深的意识到今年的对话系统/chatbot方向是真的…