2.20更新:微软NNI已经升级到0.5.1版,增加了中文说明,对常见的自动调参算法也有介绍,建议去看看
Microsoft/nnigithub.com11.06更新:自动调参,推荐微软的NNI:Microsoft/nni 。用了很久了,很好用,自动调出来的参数能让人学到很多东西,有空单独开一篇讲讲心得。
AutoML的层次
首先,常说的AutoML,对于数据挖掘和深度学习两个领域来说,几乎是完全不一样的的东西。
- 数据挖掘的 关注自动化特征工程,模型选择,自动训练最好能生成代码,数据偏移检测
- 深度学习的 关注网络结构的设计和其参数的调节
数据挖掘的AutoML已经很成熟了,以下仅对深度学习中的AutoML展开,而深度学习中的AutoML,其实也是包含两个层次的:
- 自动调参器(优化)
- 针对一个目标,调节超参数,包括网络cell类型,网络神经元数量,层数,超参数等。自动模型压缩也应当包含在这里面。
- 自动生成网络(设计)
- 关注拓扑结构的变化,关注结构的演变,称为神经架构搜索
AutoML的典型用例:
虽然通过高维度矩阵可以表达成超参数,进而变成优化问题。但是统一两个架构所需要的功夫很多。还不如先搜索一堆block,然后用优化选择最好的block,其中压缩可以在block层面完善。
因此,我认为未来2年内的AutoML工作流应当是:
- 自动设计或手工设计设计出一些block(设计block的时候,应当人为规定“计算量不能超过n FLOPS”等规则。)
- 用自动调参对这些block及其参数进行组合并获得最好的效果
以AutoML指导深度学习网络设计
从AutoML中我们可以学到很多网络调参经验,包括:
- 对参数分布进行高斯假设,然后跑最有希望的超参(借鉴贝叶斯优化调参)
- 贝叶斯优化,看这篇博客:https://blog.csdn.net/cqzz513524327/article/details/72772205/)
- 进一步看看这篇综述(https://arxiv.org/pdf/1807.02811.pdf)
- 我的理解:首先选一些超参数跑出一些结果点,然后对参数的分布进行GMM假设(即符合高斯过程),然后逐次根据已知点的结果预测下一个可能获得最小点的参数,然后把这个参数跑出结果,更新参数分布。
- 有点像EM。
- 实现上可以用HyperOpt或者SMAC3库进行预测,如HyperOpt就会用LGB做预测器)
2. 对参数进行简单预测,杜绝瞎调:
-
- 对低维参数做线性回归预测调参,高维度参数用树模型调参,对于效果不好的,我们加入一些本次训练的特征进行预测。比如说把前一半的loss曲线映射成一个特征向量,直接预测最终性能
- 线性回归跟贝叶斯调参的优缺点比较:
缺点:线性模型预测假设模型超参数界是线性可分的,性能大概会比贝叶斯差一点吧,而且可能需要除了超参数本身外多方面的特征(比如模型参数量,单次inferrance速度,模型计算量,等)。
优点:比较容易实现和可视化,而且,在实际项目中往往需要对性能和速度做权衡,线性可视化有助于决策者选择优选方案。
-
- 建议先使用线性模型进行调参优化,随后结合业务确定性能limit(比如,inferrance速度不能大于10ms)。确定性能界后再用贝叶斯为线性模型增加最好的数据点
3. 学习自动神经结构搜索优化过程中的行为
AutoML需要解决的三个核心问题
- 模型自动化训练和反馈
- 已经存在许多开源框架,比如Ray,pocketFlow,而且基于Pytorch或者TensorFlow实现这一框架不难,关键是谁的好用,这一块还需要使用和调研
- 模型优化策略
- 有很多方法,包括LSTM,强化学习,拉格朗日优化,随机搜索等,这一块会频繁变动而且已成为研究热点
- 运算速度
- 基于压缩的方法,已经可以大规模应用以提高运算速度
- 使用云服务可以大幅加速
AutoML的本质问题
- 可行网络结构/网络参数在所有网络结构中仅占很小的一部分,在这个基础上对可行的网络参数和结构进行预测的话,需要满足网络参数的流型连续的假设,这一点如果被证伪,那么所有autoML只不过是更高级的穷举和规则而已
AutoML库举例
Ray(实测可用的超参调节器,界面较差)github.com NNI(更好的超参调节器,支持yarn,k8s)github.com melodyguan/enas(可以探索RNN和CNN结构)github.com ClimbsRocks/auto_ml (适用于传统机器学习的automl库)github.com- 另外,给出一些工具
极简AutoML
本文在写作过程中觉得许多超参数调节器太臃肿,写了一个单文件的例子供大家参考,其中,超参数调节分成三个角色:代码,调度策略,调度器
- 代码不多说
- 调度策略是目前的研究热点,未来,大多数的超参数调节器将会把最新调度策略通过API形式开放,而不是像现在这样每一个调度策略都单独一个github repo.
- 调度器就是代码和策略的桥梁。基本上只要实现:实验调度(启动,停止),获取代码运行状态给调度策略,从调度策略获得指令并执行
实现如下,请参考:
simple_automl(单文件超参数优化,仅用于本文验证automl可行性)github.com为了精简代码,这里头的调度器没有资源管理的功能,一次跑多少个实验,跑在那个GPU上,由调度策略决定。
另外,为了简单起见,训练代码不需要调起回调函数,只需要把loss print出来。也就是说,任何一份能print的代码,一行都不用改就可以用这个进行优化,至于print的解析,由调度策略实现。