【NNI】自动超参搜索

【NNI】自动超参搜索

NNI官网教程

在机器学习中我们时常需要成为调参侠,调模型的各种超参如学习率、dropout。NNI可以自动选择较好的参数,免去了手动调参的过程。

下载NNI

https://nni.readthedocs.io/en/stable/installation.html

pip install nni

加入NNI

大体上不需要修改什么,只要在之前的代码里加上下面这些:

  • 使用NNI的超参
	import nni
  	from nni.utils import merge_parameter
  
  	parser.add_argument("--lr", type=int, default=0.01, help="learning rate")
		# 。。。其他超参数
    params = parser.parse_args()
    #######
    # 下面加入NNI的参数,使用NNI的参数将之前的覆盖
    nni_params = nni.get_next_parameter() # 获得本次NNI选择的超参
    params = merge_parameter(params, nni_params) # 覆盖掉之前的超参
    #######
  • 汇报test效果
for epoch in range(num_epochs):
	score = model(data)
    ###########
    # 将每一epoch的评价指标得分汇报
    nni.report_intermediate_result({'default': best_metric})
    # NNI只会看default的指标,也可以加上其他指标供自己看,如:
    # nni.report_intermediate_result({'default': mrr, 'h1': hits_1, 'h3': hits_3, 'h10': hits_10})
    ###########
# 完成所有epoch后汇报最终得分:(NNI只会看default的指标)
nni.report_final_result({'default': mrr, 'h1': hits_1, 'h3': hits_3, 'h10': hits_10})

编写NNI启动程序

这里为了也能方便的使用sh脚本启动,在同目录编写一个新的py文件名为opt.py:

import argparse
from turtle import back
import nni
from nni.experiment import Experiment
#设置参数搜索空间:
#choice为选择列表中的一个
#loguniform为对数均匀随机选择
#uniform为均匀随机选择
search_space = {
    "num_epochs": {"_type": "choice", "_value": [100,150]},
    "batch_size": {"_type": "choice", "_value": [16]},
    "lr": {"_type": "loguniform", "_value": [0.0001, 0.1]},
    "l2": {"_type": "loguniform", "_value": [0.00001, 0.001]},
    # "margin": {"_type": "choice", "_value": [1, 2, 10]},
    "num_neg_samples_per_link": {"_type": "choice", "_value": [1, 8, 32]},
    "dropout": {"_type": "uniform", "_value": [0.1, 0.5]},
    "edge_dropout": {"_type": "uniform", "_value": [0.1, 0.5]},
    # "gnn_agg_type": {"_type": "choice", "_value": ["sum", "mlp", "gru"]},
    "rel_emb_dim": {"_type": "choice", "_value": [32, 64]},
    "attn_rel_emb_dim": {"_type": "choice", "_value": [ 32, 64]},
    "emb_dim": {"_type": "choice", "_value": [32, 64]}
}

#这里为了方便使用,也加上了argument,可以对一些不需要nni调整的参数在命令行里手动选择。
parser = argparse.ArgumentParser(description='opt')
# 要跑的数据
parser.add_argument("--dataset", "-d", type=str,
                    help="Dataset string")
# 如要使用的gpu
parser.add_argument("--gpu", type=int, default=0,
                    help="Which GPU to use?")
# 以及NNI选择的端口
parser.add_argument("--port","-p",type=int,default=8081)
params = parser.parse_args()

# 下面是一些NNI的设置
experiment = Experiment('local')
# 这里把之前的训练命令行写过来,同时可以把一些需要的但不是超参的argument加上,如数据集
experiment.config.trial_command = f'python train.py -d {params.dataset} -e {params.experiment_name} --gpu {params.gpu}'
# 选择代码的目录,这里同目录就是一个.
experiment.config.trial_code_directory = '.'
# nni工作时log放哪里
experiment.config.experiment_working_directory = './experiments'
# 使用刚刚的搜索空间
experiment.config.search_space = search_space
# 搜索模式
experiment.config.tuner.name = 'TPE'
experiment.config.tuner.class_args['optimize_mode'] = 'maximize'
# 做几次实验?
experiment.config.max_trial_number = 100
# 并行数
experiment.config.trial_concurrency = 1
# 一次最多跑多久?
experiment.config.max_trial_duration = '12h'
# 把刚刚的port拿来启动NNI
experiment.run(params.port)

开始训练

直接命令行:

python opt.py -d xx -e xx --gpu 1 -p 8082

这样需要一直开着终端,可以用nohup:

nohup python opt.py -d xx -e xx --gpu 1 -p 8082 > xx.log 2>&1 &

查看

运行起来后会输出以下:(使用nohup则是在log文件里)

nohup: ignoring input
[2022-10-24 19:14:34] [32mCreating experiment, Experiment ID: [36m6ngbaxuj[0m
[2022-10-24 19:14:34] [32mStarting web server...[0m
[2022-10-24 19:14:35] [32mSetting up...[0m
[2022-10-24 19:14:35] [32mWeb portal URLs: [36mhttp://127.0.0.1:8082 http://xxx.xxx.xxx.xxx:8082[0m

打开等待即可:

【NNI】自动超参搜索_第1张图片

你可能感兴趣的:(机器学习,机器学习,深度学习,人工智能,1024程序员节)