在机器学习、深度学习中,有两类参数,一类需要从数据中学习和估计得到,称为模型参数(Parameter);另一类需要人为设定,称为超参数(Hyperparameter),例如学习率、正则化系数等。
HPO(Hyperparameter Optimization, 超参数优化 )是指用自动化的算法来优化超参数,从而提升模型的精度、性能等指标。使用HPO能力,可以快速高效地在超参数空间中测试选择最佳的超参数组合,节省大量人力和时间。
当前提供的HPO能力支持Random、ASHA、BOHB、BOSS、PBT等HPO算法,适用于常见的深度神经网络的超参数优化,包括单目标优化和随机帕累托的多目标超参选择。
了解帕累托机制主要需要了解以下两个概念:
HPO功能会通过HPO算法搜索出满足帕累托前沿的一系列超参数组合,如图1代表的是以准确率Acc和时延Latency为优化目标搜索出的超参的情况。
其中,橙色圆点为搜索出来的在准确率Acc和时延Latency维度都优于蓝色圆点代表的超参,即橙色圆点代表的超参支配蓝色圆点代表的超参。
在橙色圆点代表的一系列超参中,对于任何一个超参,没有其他参数能在准确率Acc和时延Latency维度均优于它,即没有其他参数能支配它,橙色圆点代表的一系列超参构成帕累托前沿。
export PYTHONPATH={CANN包安装路径}/ascend-toolkit/latest/tools:$PYTHONPATH
general: parallel_search: False # 是否使用多卡进行HPO搜索 parallel_fully_train: False# 是否使用多卡进行fullytrain search_timeout: 10000 # HPO阶段的搜索timeout,单位为秒,不配置则使用 31536000 worker: timeout: 150 # HPO阶段/fullytrain阶段单个训练任务的timeout,单位为秒,不配置则使用 `search_timeout` logger: level: info # 日志级别,debug|info|warn|error| task: local_base_path: /home/xxx # 任务路径,默认值为启动HPO任务的工作路径,请根据实际路径配置 pipeline: [hpo, fullytrain] # 与后续阶段的名称保持一致,需为[hpo, fullytrain]或[hpo]
hpo: pipe_step: type: CustomSearchPipeStep# 不需修改,也可设置为SearchPipeStep search_algorithm: # 搜索算法 …… search_space: # 搜索空间 …… trainer: # trainer ……
search_algorithm: type: RandomSearch objective_keys: 'accuracy' policy: num_sample: 10 #超参采样的总组数,可选,默认值为10
search_space: type: SearchSpace hyperparameters: #指定的参数类型和范围 - key: lr type: FLOAT range: [0.001,0.01]
trainer: type: HpoRunner # 不需修改 objectives: #待优化目标,值需与hpo.search_algorithm.objective一致,取值为'MAX'或'MIN' accuracy: 'MAX' avg_time: 'MIN' train_script: /home/xxx/hpo_sample.py #用户训练工程的启动脚本,根据实际情况配置 pkg_path: /home/xxx/pkg_path #可选,用户训练工程代码所在路径,HPO工具会将该路径加入pythonpath other_args: #可选,不需进行调优的固定参数 momentum: 0.9 # 带值参数,拼接命令为 --momentum=0.9 pretrained: ~ # 不带值参数,拼接命令为 --pretrained has_config_arg: True config_arg_name: config_file config_file_path: /home/xxx/config.yml enable_arg_check: True #参数匹配方式
fullytrain: pipe_step: type: TrainPipeStep trainer: ref: hpo.trainer #复用hpo阶段的配置
objective_key, objective_value = "accuracy", #实际训练中的数值 json_path = './{}.json'.format(objective_key) if os.path.exists(json_path): os.remove(json_path) with os.fdopen(os.open(json_path, os.O_WRONLY | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR), 'w') as fout: json.dump({objective_key: objective_value}, fout)
pipestep_env = os.getenv("PIPESTEP") if pipestep_env == "hpo": #标识当前子进程阶段,取值为 "hpo" 或 "fullytrain",以此指定 epochs 数量等训练参数。 epochs = int(os.getenv("EPOCHS", opt.epochs))
部分HPO算法向不同的子任务分配不同的训练资源(即epochs),因此子进程需要读取主进程指定的epochs配额。“EPOCHS”取值为'0'、'1'、'2'……,用于 hpo 阶段,fullytrain 阶段会取消该环境变量。
opt.device = "npu:{}".format(os.getenv("DEVICE_ID", '0')) #在多卡搜索/训练时,主进程为子进程指定NPU卡的id,取值为'0'、'1'、'2'……
export DEVICE_ID=3 # 可选,指定实际使用的 NPU vega hpo.yml #根据实际文件名进行修改
export NPU_VISIBLE_DEVICES=3,4 # 使用多卡搜索/训练时的 NPU vega hpo.yml #根据实际文件名进行修改
2022-08-21 07:08:11.85 INFO ------------------------------------------------ 2022-08-21 07:08:11.85 INFO Pipeline end. 2022-08-21 07:08:11.85 INFO 2022-08-21 07:08:11.85 INFO task id: 0820.152508.049 2022-08-21 07:08:11.95 INFO output folder: /example/tasks/0820.152508.049/output 2022-08-21 07:08:11.95 INFO 2022-08-21 07:08:11.95 INFO running time: 2022-08-21 07:08:11.95 INFO hpo: 14:38:29 [2022-08-20 15:25:47.798652 - 2022-08-21 06:04:17.701847] 2022-08-21 07:08:11.95 INFO fullytrain: 1:03:51 [2022-08-21 06:04:17.713431 - 2022-08-21 07:08:09.083200] 2022-08-21 07:08:11.96 INFO 2022-08-21 07:08:11.115 INFO result: 2022-08-21 07:08:11.116 INFO 6: {'hps': {'batch_size': 16, 'lr': 0.0058436978394671175}, 'accuracy': 0.835} 2022-08-21 07:08:11.116 INFO ------------------------------------------------
{task_id} ├── logs │ ├── fullytrain_worker_{worker_id}.log # 第worker_id个worker上进行fullytrain的日志文件 │ ├── hpo_worker_{worker_id}.log # 第worker_id个worker上进行hpo的日志文件 │ └── pipeline.log ├── output │ ├── fullytrain │ │ ├── output.csv # 优化指标值汇总文件 │ │ └── performance_{worker_id}.json # 搜索出的最佳优化指标值 │ ├── hpo │ │ ├── hps_{worker_id}.json # 搜索出的最佳超参值 │ │ ├── output.csv # 优化指标值汇总文件 │ │ └── performance_{worker_id}.json # 搜索出的最佳优化指标值 │ ├── hpo.yml # 配置文件 │ └── reports.json # hpo任务的报告文件 └── workers ├── fullytrain │ ├── {worker_id} │ └── {worker_id} │ └── performance_{worker_id}.json # 优化目标值 └── hpo ├── {worker_id} └── {worker_id} ├── hps_{worker_id}.json # 超参值 └── performance_{worker_id}.json # 优化目标值