调参是深度学习中的必经过程,研究者们往往需要花费大量的时间进行调参,以获取最好效果的模型参数。对于参数规模不大的小模型,手工运行实验进行参数调优还是可以接受的方法,但当遇上大模型时,只凭人工进行参数优化就会变得难以实操,也难以高效利用GPU集群的强大算力。
为了解决这一问题,幻方 AI 基于萤火集群的特性,研发了一套辅助调参工具,Autotune。用户只需要设定好参数搜索范围,在幻方萤火集群上发起训练,Autotune 会自动帮您尝试所有的参数组合,合理分配算力进行测试,最后统计输出不同参数下的模型表现。
设计思路
hfai.autotune
旨在降低调参门槛,改动少部分代码即可实现自动调参。
萤火集群可以通过 hfai 命令或在 JupyterLab 中手动发起的方式来提交训练任务,然而这些方法并不能支持大批量的任务发起。因此在 Autotune 的设计中我们选择 create_experiment_v2 接口,实现一次提交多任务的目标。
用户在使用时设定需要测试的参数组或直接指定参数范围,Autotune 将需要调优的参数进行组合进行网格搜索。这里需要创建多个可以同时训练的任务,在算力允许的范围内运行尽可能多的任务以加速调参过程。
不同任务的训练结果会集中记录在一个日志文件夹中,统计输出时会从这个文件夹中读取所有参数的结果,进行排序后返回。
任务发起
介绍完 hfai.autotune
的设计思路之后,那么其如何使用呢?
只需要加入一行 Python 代码即可:
hfai.autotune.run(config, args, log_dir)
这里必备的三个参数是:
config
: 萤火集群训练任务的基本配置文件,参考配置文件格式。args
: 调参参数,在代码中指定。log_dir
: 记录训练结果的文件夹,在代码中指定。
接下来就可以开始调参优化了。具体的,有两种主要的参数搜索模式:
- 发起固定参数搜索任务
- 发起参数网格搜索任务
发起固定参数搜索任务
输入参数为列表形式,每个列表内的元素是包含了超参数的一个字典,如下例所示:
import hfai
args = [{"lr":0.1, "bs":256}, {"lr":0.3, "bs":64}]
hfai.autotune.run(config, args, log_dir)
此时,Autotune 会分别使用args列表中的两组参数发起两个调参任务。
发起参数网格搜索任务
输入参数为字典形式,每个超参数通过指定其搜索范围来发起任务。
每个参数的输入可以有两种形式:
- 对应一个三元组表示参数搜索的起始值,终止值以及搜索步长
- 对应一个列表表示参数所有可能的取值
如下例所示:
import hfai
args = {"lr":(0.002, 0.006, 0.001), "bs":(64, 320, 64)}
hfai.autotune.run_grid_search(config, args, log_dir)
args = {"lr":[0.002, 0.003, 0.004, 0.005], "bs":[64, 128, 192, 256]}
hfai.autotune.run_grid_search(config, args, log_dir)
此时,Autotune 会分别遍历args中的 lr
和 bs
两个参数的所有取值,并将其组合成最终搜索的参数组。例如在这里 lr
共有4个不同取值,而 bs
也有4个不同取值,那么就会发起总共 4 x 4 = 16
个使用不同 lr
和 bs
组合的调参任务。
本地调试
为了方便用户在本地进行代码调试,Autotune 提供了一键调试模式,set_debug_mode
,方便用户在本地运行代码,测试无误后再发至集群进行大规模搜参。使用案例如下:
import hfai
hfai.autotune.set_debug_mode()
args = {"lr":(0.002, 0.006, 0.001), "bs":(64, 320, 64)}
hfai.autotune.run(config, args, log_dir)
在本地调试一组任务时,Autotune 只会使用所有参数组中的任意一组参数发起单个训练任务。默认情况下,Autotune 在非调试模式下运行。
训练代码改动
hfai.autotune
通过尽量少的训练代码改动来支持自动调参功能。在训练代码中只需要在每次训练开始之前调用 Autotune 提供的 get_args
接口来获取任务使用的参数组合,将参数应用到训练配置中就可以进行训练。在训练完成后,同样只需要调用提供的 report
方法就可以将模型测试结果汇报并记录。
如下例所示:
import hfai
args = hfai.autotune.get_args()
lr, batch_size = float(args["lr"]), float(args["bs"])
# ...
# training codes
# ...
# finish training
metrics = {"prec":0.81, "recall":0.79, "loss":0.15}
hfai.autotune.report(metrics)
结果统计
训练结束后,Autotune 会对每个参数训练得到的结果进行汇总统计,按照指定的方式对指标进行排序,返回表现优秀的实验。
import hfai
hfai.autotune.show_result(log_dir, metric="acc")
下图展示了某任务的调参训练结果: