hfai.autotune | 一行代码,自动调参

Daylight    September 05, 2022

调参是深度学习中的必经过程,研究者们往往需要花费大量的时间进行调参,以获取最好效果的模型参数。对于参数规模不大的小模型,手工运行实验进行参数调优还是可以接受的方法,但当遇上大模型时,只凭人工进行参数优化就会变得难以实操,也难以高效利用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: 记录训练结果的文件夹,在代码中指定。

接下来就可以开始调参优化了。具体的,有两种主要的参数搜索模式:

  1. 发起固定参数搜索任务
  2. 发起参数网格搜索任务

发起固定参数搜索任务

输入参数为列表形式,每个列表内的元素是包含了超参数的一个字典,如下例所示:

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中的 lrbs 两个参数的所有取值,并将其组合成最终搜索的参数组。例如在这里 lr 共有4个不同取值,而 bs 也有4个不同取值,那么就会发起总共 4 x 4 = 16 个使用不同 lrbs 组合的调参任务。

本地调试

为了方便用户在本地进行代码调试,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")

下图展示了某任务的调参训练结果:

结果截图


本文作者: Daylight


您可以转载、不违背作品原意地摘录及引用本技术博客的内容,但必须遵守以下条款: 署名 — 您应当署名原作者,但不得以任何方式暗示幻方为您背书,亦不会对幻方的权利造成任何负面影响。 非商业性使用 — 您不得将本技术博客内容用于商业目的。 禁止演绎 — 如果基于该内容改编、转换、或者再创作,您不得公开或分发被修改内容,该内容仅可供个人使用。