文档
注册

超参数优化

概述

在机器学习、深度学习中,有两类参数,一类需要从数据中学习和估计得到,称为模型参数(Parameter);另一类需要人为设定,称为超参数(Hyperparameter),例如学习率、正则化系数等。

HPO(Hyperparameter Optimization, 超参数优化 )是指用自动化的算法来优化超参数,从而提升模型的精度、性能等指标。使用HPO能力,可以快速高效地在超参数空间中测试选择最佳的超参数组合,节省大量人力和时间。

当前提供的HPO能力支持Random、ASHA、BOHB、BOSS、PBT等HPO算法,适用于常见的深度神经网络的超参数优化,包括单目标优化和随机帕累托的多目标超参选择。

帕累托机制

了解帕累托机制主要需要了解以下两个概念:

  • 帕累托支配:一个超参A在任何一个优化目标维度都优于另外一个超参B,称为超参A支配超参B。
  • 帕累托前沿:在一系列超参中,对于任何一个超参,没有其他超参能支配它。

HPO功能会通过HPO算法搜索出满足帕累托前沿的一系列超参数组合,如图1代表的是以准确率Acc和时延Latency为优化目标搜索出的超参的情况。

图1 以Acc和Latency为优化目标搜索出的超参信息

其中,橙色圆点为搜索出来的在准确率Acc和时延Latency维度都优于蓝色圆点代表的超参,即橙色圆点代表的超参支配蓝色圆点代表的超参。

在橙色圆点代表的一系列超参中,对于任何一个超参,没有其他参数能在准确率Acc和时延Latency维度均优于它,即没有其他参数能支配它,橙色圆点代表的一系列超参构成帕累托前沿。

前提条件

  • 已安装1.1.3版本的pandas依赖包。
  • 在运行的训练环境中将ascend_automl/的父目录加入PYTHONPATH中:
    export PYTHONPATH={CANN包安装路径}/ascend-toolkit/latest/tools:$PYTHONPATH

HPO工具运行流程

图2 工具运行流程
  1. 超参采样:HPO工具读取配置文件(由用户自行准备),使用HPO算法在搜索空间中进行多组超参的采样。
  2. 启动训练任务:对于每组采样得到的超参,HPO工具在子进程中启动相应的训练任务。
  3. 返回指标:每个训练任务将待优化指标值,如精度、时延等,保存到json文件中,由HPO工具读取。
  4. 比较选择:HPO工具对多组超参对应的指标值进行比较,选出较优的一组或多组超参。
  5. fullytrain:HPO工具使用较优超参,进行训练任务的fullytrain。

操作步骤

  1. 进入{CANN包安装路径}/ascend-toolkit/latest/tools/ascend_automl/examples/docs/hpo目录,已提供示例文件hpo.yml,建议拷贝至当前运行目录修改即可。
  2. 编写hpo.yml配置文件,进行任务配置。
    任务配置主要包含通用配置、hpo阶段和fullytrain阶段的配置,请参考以下加粗字体信息进行通用配置。
    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]
    • 如果配置了“ search_timeout”“ worker: timeout”会在超时时尝试停止任务,在某些情况下可能会停不掉,造成未停掉的任务显存占用,导致后续任务显存不足。
    • 若不配置“search_timeout”字段,则使用默认值 “31536000”。若不配置“worker: timeout”字段,将使用“search_timeout”
  3. 配置hpo阶段,主要配置搜索算法(search_algorithm)、搜索空间(search_space)和训练任务(trainer)信息。请参考以下加粗字体信息配置hpo阶段任务类型。
    hpo:
      pipe_step:
        type: CustomSearchPipeStep# 不需修改,也可设置为SearchPipeStep
      search_algorithm:		# 搜索算法
        ……
      search_space:		# 搜索空间
        ……
      trainer:		# trainer
        ……
    “pipe_step: type”若要支持多卡搜索,需要配置为 “SearchPipeStep”,但 “SearchPipeStep” 不支持 “general.search_timeout”
    1. search_algorithm配置。HPO 命令行工具能力支持 Random、ASHA、BOHB、BOSS、PBT 等 HPO 算法,以Random 搜索算法为例,参考以下加粗字体信息进行配置,其他算法配置请参考超参数优化支持的搜索算法说明
        search_algorithm:
          type: RandomSearch
          objective_keys: 'accuracy'
          policy:
            num_sample: 10    #超参采样的总组数,可选,默认值为10
    2. search_space配置。HPO 工具将根据“hpo.search_space.hyperparameters”指定的参数类型和范围,进行超参数值的采样。参数类型支持 CATEGORY、BOOL、INT、INT_EXP、FLOAT、FLOAT_EXP 等。参考以下加粗字体信息进行配置。
        search_space:
          type: SearchSpace
          hyperparameters:    #指定的参数类型和范围
              -    key: lr
                   type: FLOAT
                   range: [0.001,0.01]
    3. trainer配置。HPO工具将从search_space中进行超参采样,并结合trainer中的配置内容,组合一个完整的训练任务启动命令,并在子进程中运行。
        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   #参数匹配方式
    • “has_config_arg”默认为“False”,若设置为“True”,需同时配置“config_arg_name”“config_file_path”
    • “enable_arg_check”决定了参数匹配方式,设置为“True”时将对参数进行检查,不匹配的参数将不会传给训练脚本。
  4. 配置fullytrain阶段。参考以下加粗字体信息进行配置。
    fullytrain:
      pipe_step:
        type: TrainPipeStep
      trainer:
        ref: hpo.trainer    #复用hpo阶段的配置
  5. 进行源码修改。HPO主进程与训练任务子进程之间,需要进行信息交互,用户需要修改源码,从环境变量中获取部分变量值,并将需要传回给主进程的数值保存在json文件中。参考同目录下hpo_sample.py文件,修改用户自行准备的训练脚本。
    1. dump 待优化指标值到 json 文件。参考样例 hpo_sample.py 中的 modification 1 和 modification 4进行如下配置。
      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)
      • 用户可将dump_objective()函数添加在脚本中,并以dump_objective(objective_key, objective_value)的格式进行调用,将待优化指标值保存至json文件中。HPO主进程将从这一json文件中读取指标值,并以此为依据进行后续超参的比较。
      • objective_key需与步骤3中的hpo.search_algorithm.objective_keys保持一致。
    2. 获取 PIPESTEP 与 EPOCHS 环境变量。若配置hpo阶段“search_algorithm”的类型不是RandomSearch搜索算法,则需要从环境变量获取实际指定的脚本训练 epochs,请参考样例 hpo_sample.py 中的 “modification 3”进行如下配置。
      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 阶段会取消该环境变量。

    3. 获取 DEVICE_ID 环境变量。进行多卡训练时,训练脚本需要获取实际分配的 DEVICE_ID,参考样例 hpo_sample.py 中的 modification 3进行如下配置。若为单卡搜索/训练,用户可自行指定NPU卡号,不需做对应修改。
      opt.device = "npu:{}".format(os.getenv("DEVICE_ID", '0'))    #在多卡搜索/训练时,主进程为子进程指定NPU卡的id,取值为'0'、'1'、'2'……
  6. 启动超参数调优任务。
    • 单卡训练,使用以下命令进行任务启动:
      export DEVICE_ID=3	# 可选,指定实际使用的 NPU
      vega hpo.yml     #根据实际文件名进行修改
    • 多卡训练,需要在步骤3通用配置时,“parallel_search”:配置为“ True”,hpo:阶段“pipe_step: type”配置为 “SearchPipeStep”,使用以下命令进行任务启动:
      export NPU_VISIBLE_DEVICES=3,4	# 使用多卡搜索/训练时的 NPU
      vega hpo.yml     #根据实际文件名进行修改
  7. 查看超参调优结果。运行界面中会打印超参调优结果,参考如下。
    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 ------------------------------------------------
    • 若结果值出现 9e+16 或者 -9e+16,说明任务运行超时,或者没有正确的保存优化指标值。
    • 其中输出结果中 result 部分为 fullytrain 中对应 {worker_id} 的调参结果。
    • 在结果所示路径下会生成tasks文件夹,tasks文件夹下有名为{task_id}的文件夹,可查看运行日志、运行结果等数据。
      {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  # 优化目标值
搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词