NNI官网教程
在机器学习中我们时常需要成为调参侠,调模型的各种超参如学习率、dropout。NNI可以自动选择较好的参数,免去了手动调参的过程。
https://nni.readthedocs.io/en/stable/installation.html
pip install 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) # 覆盖掉之前的超参
#######
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})
这里为了也能方便的使用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
打开等待即可: