[Ray.Tune]使用心得(待完善)
Posted MarToony|名角
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Ray.Tune]使用心得(待完善)相关的知识,希望对你有一定的参考价值。
首先,report中参数,是自行指定的,而参数对应的值需要在程序中有出现,这一点不需要赘述。
同时在report中指定的参数,将会在Ray运行的过程中以表格的形式展现。
比如,
tune.report(loss=(mean_loss), accuracy=test_accuracy, accuracy2= test_accuracy)
# =======================
+---------------------+------------+---------------------+------+--------+------------------+---------+------------+-------------+
| Trial name | status | loc | lr | iter | total time (s) | loss | accuracy | accuracy2 |
|---------------------+------------+---------------------+------+--------+------------------+---------+------------+-------------|
| DEFAULT_8aa09_00000 | TERMINATED | 172.27.67.94:290338 | 0.01 | 5 | 137.438 | 1.39491 | 53.7037 | 53.7037 |
| DEFAULT_8aa09_00001 | TERMINATED | 172.27.67.94:290340 | 0.1 | 1 | 29.1316 | 1.50628 | 48.8889 | 48.8889 |
+---------------------+------------+---------------------+------+--------+------------------+---------+------------+-------------+
其次,在report中指定的指标,自然也可以当作相关API中参数的候选值被使用,比如接口analysis.get_best_config(metric="accuracy", mode="max"))
logger.info("Best config: ".format(analysis.get_best_config(metric="accuracy", mode="max")))
logger.info("Best config: ".format(analysis.get_best_config(metric="accuracy2", mode="max")))
logger.info("Best config: ".format(analysis.get_best_config(metric="loss", mode="min")))
# =================================
Best config: 'lr': 0.01
Best config: 'lr': 0.01
Best config: 'lr': 0.01
默认地,ray.tune运行时包含的字典的键有以下:
以上内容是在超参数仅学习率,且学习率可选值未0.1和0.01两个值时得到的结果。
该结果通过analysis.dataframe()
函数输出,并通过to_csv
保存为CSV文件得到。
除此之外,还有一种全局控制输出字段的方式是:
from ray.tune import CLIReporter
reporter = CLIReporter(metric_columns=["loss", "mean_accuracy2", "training_iteration"])
# =======================
+---------------------+------------+---------------------+------+---------+----------------------+
| Trial name | status | loc | lr | loss | training_iteration |
|---------------------+------------+---------------------+------+---------+----------------------|
| DEFAULT_2d6b3_00000 | RUNNING | 172.27.67.94:295017 | 0.01 | 1.54909 | 1 |
| DEFAULT_2d6b3_00001 | TERMINATED | 172.27.67.94:295016 | 0.1 | 2.01156 | 1 |
+---------------------+------------+---------------------+------+---------+----------------------+
在CLIReporter
中指定的指标,将会取代reporter函数的指定内容,但并不是完全覆盖,因为CLIReporter中指定的指标只有在reporter中被赋予值后才会在状态表中显示。
Tune的常用API参考界面
1 搜索空间:提供了定义超参数搜索空间的函数。
需要注意,预使用的搜索算法要衡量是否与搜索空间中的函数相适用,因为sample_from和grid_search通常并不受支持。
2 搜索算法:开源优化库的包装器,特定的搜索空间定义方式,用于高效的超参数选择
3 调度程序:提前终止不良试验,暂停试验,克隆试验以及更改正在运行的试验的超参数,以优化超算数
4 教程和常见问题:指导如何选择搜索算法和调度算法以及重现试验
5 使用 RAY TUNE 调整超参数:Pytorch官网对Ray Tune的介绍,包含一个完整的小栗子
+ 经典的框架
1 凤头
即,配置一些基本的内容。
一共包含上面六个部分,但是除此之外,还有一处代码设计需要注意:一般地,参数值可以分为两种,需要调整config和不需要调整的参数arg=parser.parse_args()。分开的方式就是:对于tune.run中调用的主函数spot,通过function.partial方法将其与arg捆绑在一起。
搜索空间的定义方式
tune.run(
trainable,
config=
"param1": tune.choice([True, False]), # 从所列出的有限值中选择
"bar": tune.uniform(0, 10), # 从一个遵从均匀分布的生成器中选择
"alpha": tune.sample_from(lambda _: np.random.uniform(100) ** 2),
"const": "hello", # 面向常量
"bar": tune.grid_search([True, False]),
)
完整的代码如下:
def spot(arg, config, checkpoint_dir=None):
import copy
arg = copy.deepcopy(arg)
# 为了尽可能地不去修改原始的代码文件,将yaml文件中需要调整的参数在该函数中替换修改。
arg.base_lr = config["lr"]
arg.batch_size = config["batch_size"]
arg.weight_decay = config["weight_decay"]
arg.step = config["step"]
arg.optim_args["momentum"] = config["momentum"]
arg.warm_up_epoch = config["warm_up_epoch"]
processor = Processor(arg, logdir, model_save_dir)
processor.start()
if __name__ == '__main__':
dataType = "skeletons" # ["images",skeletons]
yamlConfigPath = './config/dad/clip225/none/agcn/train_bone.yaml'
logger.info("配置文件:".format(yamlConfigPath))
parser = get_parser(yamlConfigPath)
p = parser.parse_args() # 当前py文件中预定义好的参数字典。
if p.config is not None:
with open(p.config, 'r') as f:
default_arg = yaml.full_load(f) # yaml文件中的参数字典
key = vars(p).keys()
for k in default_arg.keys():
if k not in key:
print('WRONG ARG: '.format(k))
assert (k in key)
parser.set_defaults(**default_arg)
arg = parser.parse_args()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
init_seed(arg.seed)
# 所有的参数在这里之前都要确定下来。
with open('/config.yaml'.format(logdir), 'w') as f:
yaml.dump(vars(arg), f)
config =
"lr": tune.choice([0.1, 0.01, 0.001, 0.05, 0.005]),
"batch_size": tune.grid_search([16, 32, 64, 128]),
"weight_decay": tune.grid_search([0.0001, 0.0003, 0.0005]),
"step": tune.grid_search([[45, 55, 65],
[30, 50],
[20, 40, 60]]),
"momentum": tune.grid_search([0.7, 0.8, 0.9]),
"warm_up_epoch": tune.grid_search([0, 5, 10])
scheduler = ASHAScheduler(
metric="accuracy",
mode="max",
max_t=65,
grace_period=1,
reduction_factor=2)
reporter = CLIReporter(
metric_columns=["loss", "accuracy", "training_iteration"])
analysis = tune.run(
partial(spot, arg),
num_samples=200,
resources_per_trial="cpu": 16, "gpu": 1,
config=config,
scheduler=scheduler,
progress_reporter=reporter
)
2 猪肚
核心还是Processor类,由其中的start函数启动训练。
原始的项目代码基本上没有修改,经由spot函数连接Ray.tune和processor。
耦合度得到提升。
3 龙尾
# 获取结果的 dataframe
import pandas as pd
pd.set_option('display.max_columns', None)
# 1 返回一个由所有实验信息构建成的pandas.DataFrame对象。
df = analysis.dataframe()
df.to_csv("df_testcsv.csv")
logger.info("df:\\n".format(df))
# 2 返回 List of all dataframes of the trials.
dfs = analysis.trial_dataframes
logger.info("dfs:\\n".format(dfs))
# 3 显示各个实验的结果。
from matplotlib.pyplot import plt
ax = None # This plots everything on the same plot
for d in dfs.values():
ax = d.loss.plot(ax=ax, legend=True)
plt.xlabel("epoch")
plt.ylabel("Test Accuracy")
plt.show()
# 4 显示最好的配置结果。
logger.info("Best config: ".format(analysis.get_best_config(metric="accuracy", mode="max")))
logger.info("Best config: ".format(analysis.get_best_config(metric="loss", mode="min")))
best_trial = analysis.get_best_trial("loss", "min", "last")
logger.info("Best trial config1: ".format(best_trial.config))
logger.info("Best trial final validation loss: ".format(best_trial.last_result["loss"]))
logger.info("Best trial final validation accuracy: ".format(best_trial.last_result["accuracy"]))
best_trial = analysis.get_best_trial("accuracy", "max", "last")
logger.info("Best trial config2: ".format(best_trial.config))
logger.info("Best trial final validation loss: ".format(best_trial.last_result["loss"]))
logger.info("Best trial final validation accuracy: ".format(best_trial.last_result["accuracy"]))
analysis = tune.run(trainable, search_alg=algo, stop="training_iteration": 20)
best_trial = analysis.best_trial # Get best trial
best_config = analysis.best_config # Get best trial's hyperparameters
best_logdir = analysis.best_logdir # Get best trial's logdir
best_checkpoint = analysis.best_checkpoint # Get best trial's best checkpoint
best_result = analysis.best_result # Get best trial's last results
best_result_df = analysis.best_result_df # Get best result as pandas dataframe
# 5 加持最后的配置参数得到的结果。
import copy
arg = copy.deepcopy(arg)
arg.base_lr = best_trial.config["lr"]
arg.batch_size = best_trial.config["batch_size"]
arg以上是关于[Ray.Tune]使用心得(待完善)的主要内容,如果未能解决你的问题,请参考以下文章
Ray[tune] for pytorch TypeError: ray.cloudpickle.dumps
[Ray.Tune] [已解决] TypeError: ray.cloudpickle.dumps
[Ray.Tune] [已解决] TypeError: ray.cloudpickle.dumps
如何在 Ray Tune 中定义与搜索算法无关的高维搜索空间?
[Ray.Tune] [已解决] Queue objects should only be shared between processes through inheritance