使用ray.tune实现神经网络超参数优化
ray.tune 工作流
官方的Quickstart例子表明,ray.tune使用起来只有三步:1)定义目标函数;2)定义搜索空间;3)运行tune并输出最优结果。
使用以下功能至少需要python=3.8,ray=2.7。
from ray import train, tune
def objective(config): # ①
score = config["a"] ** 2 + config["b"]
return {"score": score}
search_space = { # ②
"a": tune.grid_search([0.001, 0.01, 0.1, 1.0]),
"b": tune.choice([1, 2, 3]),
}
tuner = tune.Tuner(objective, param_space=search_space) # ③
results = tuner.fit()
print(results.get_best_result(metric="score", mode="min").config)
目标函数
目标函数需要输入可变超参数config
,输出是评价。对于神经网络,输出一般是训练集loss或正确率等。
train.report
可以存储训练过程,用于后续优化和分析。
from ray import train, tune
def objective(config):
n_layer, n_node, lr = config["n_layer"], config["n_node"], config["lr"]
# ...
for epoch in range(epochs):
#...
train.report({"epoch": epoch, "valid_loss": valid_loss})
# ...
搜索空间
以下举例给出各类变量定义方法,其中,随机搜索的参数空间:
search_space = {
"lr": tune.sample_from(lambda spec: 10 ** (-10 * np.random.rand())),
"momentum": tune.uniform(0.1, 0.9),
"activation": tune.choice(["relu", "tanh"]),
}
网格搜索的参数空间:
"lr": tune.grid_search([0.001, 0.01, 0.1, 1.0]),
运行tune
定义调参器,可以设置使用的超参数搜索方法。
具体输入参数见以下代码:
from ray.tune.search import ConcurrencyLimiter
from ray.tune.search.bayesopt import BayesOptSearch
tuner = tune.Tuner(
objective, # 函数名
tune_config=tune.TuneConfig(
metric="valid_loss", # 被train.report的变量
mode="min", # 取最小值
search_alg=algo, # 使用其他参数优化方法
num_samples=num_samples, # 运算次数(随机n次/网格搜索n次)
),
param_space=search_space,
)
results = tuner.fit()
# 贝叶斯优化
algo = BayesOptSearch(utility_kwargs={"kind": "ucb", "kappa": 2.5, "xi": 0.0})
algo = ConcurrencyLimiter(algo, max_concurrent=4)
结果分析
best_result = results.get_best_result()
result_1 = best_result.matrics_dataframe
print(result_1[["epoch", "valid_loss"]])
输出为
epoch valid_loss
0 0 57.801731
1 1 32.909950
2 2 25.675837
3 3 21.934740
4 4 18.740681
5 5 17.450092
...
14 14 12.594048
官网链接:RAY