optuna 自动化调参利器

人工智能20

Optuna是一个自动超参数优化软件框架,专为机器学习而设计。它具有命令式、 运行时定义的用户 API。Optuna的用户可以动态地构建超参数的搜索空间。
optuna API

使用optuna

Optuna 与几乎所有可用的机器学习框架一起使用:TensorFlow、PyTorch、LightGBM、XGBoost、CatBoost、sklearn、FastAI 等。

安装optuna

 pip install optuna

每个 Optuna 超参数调整会话称为学习。我们通过调用create_study方法来实例化一个学习会话。我们可以将几个重要的参数传递给这个方法,如下所示

import optuna
study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler())

direction

direction value 可以设置为maximize或minimize,具体取决于我们的超参数调整的最终目标。

  • 如果目标是通过准确度、F1 分数、精确度或召回率等指标来提高性能,则将其设置为maximize.

  • 如果目标是减少损失函数,例如 log-loss、MSE、RMSE 等,则将其设置为minimize.

sampler

sampler value 指示您希望 Optuna 实施的采样器方法。您可以选择多个采样器选项,例如:

  • GridSampler:根据定义的搜索空间中的每个组合选择一组超参数值。
  • RandomSampler:从定义的搜索空间中随机选择一组超参数值。
  • TPESampler:这是sampler我们使用 Optuna
    的默认设置。它基于贝叶斯超参数优化,是一种有效的超参数调整方法。它将像一个随机采样器一样开始,但采样器记录了一组超级参数值的历史以及过去实验的相应目标值。然后,在前人实验的目标值集的基础上,为下一次的实验提出一组超参数值。

    [En]

    The default setting for the. It is based on Bayesian hyperparameter optimization, which is an effective hyperparameter adjustment method. It will start like a random sampler, but the sampler records the history of a set of super-parameter values and the corresponding target values for past experiments. Then, it will suggest a set of super-parameter values for the next experiment based on the promising target value set of previous experiments.

接下来,我们可以调用optimize我们学习中的方法,并将我们的objective函数作为参数之一传递。

import optuna

study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler())
study.optimize(objective, n_trials=30)

上面的n_trials参数表示您希望 Optuna 在研究中执行的试验次数。

到目前为止,我们还没有创建objective 函数。所以让我们objective首先定义搜索空间来创建我们的函数。

搜索空间定义

在每个超参数调整过程中,我们需要为采样器定义一个搜索空间。搜索空间是采样器应该从超参数中考虑的值的范围。

[En]

In each hyperparameter adjustment session, we need to define a search space for the sampler. The search space is the range of values that the sampler should consider from the hyperparameters.

例如,假设我们要调整三个超级参数:学习率、层中单元数和神经网络模型的优化器。然后,我们可以如下定义搜索空间:

[En]

For example, suppose we want to adjust three super parameters: the learning rate, the number of units in the layer, and the optimizer of the neural network model. Then, we can define the search space as follows:

def objective(trial):

    params = {
              'learning_rate': trial.suggest_loguniform('learning_rate', 1e-5, 1e-1),
              'optimizer': trial.suggest_categorical("optimizer", ["Adam", "RMSprop", "SGD"]),
              'n_unit': trial.suggest_int("n_unit", 4, 18)
              }

    model = build_model(params)

    accuracy = train_and_evaluate(params, model)

    return accuracy

在objective函数中,我们传递了一个名为 的参数trial,它来自TrialOptuna 的类。此类使 Optuna 能够记录一组选定的超参数值,并objective在每次试验中记录我们的函数值(在我们的例子中是准确性)

正如您在上面看到的,我们将每个超参数的搜索空间定义为一个名为 的字典params。对于每个超参数,我们用方法定义搜索空间的范围(最小值和最大值) suggest_*

suggest_*方法有几个扩展,具体取决于超参数的数据类型:

  • suggest_int:如果您的超参数接受一系列整数类型的数值。
  • suggest_categorical:如果您的超参数接受分类值的选择。
  • suggest_uniform:如果您的超参数接受一系列数值,并且您希望对每个值进行同样的采样。
  • suggest_loguniform:如果您的超参数接受一系列数值,并且您希望在对数域中对每个值进行同样的采样。
  • suggest_discrete_uniform:如果您的超参数接受特定区间内的一系列数值,并且您希望每个值都以同样的可能性进行采样。
  • suggest_float:如果您的超参数接受一系列浮点类型的数值。这是 , 和
    的suggest_uniform包装suggest_loguniform方法suggest_discrete_uniform

构建 PyTorch 模型、训练循环和评估目标函数

现在我们可以使用保存在params字典中的选定超参数值来构建 PyTorch 模型。接下来,我们将训练模型并评估我们的目标函数,在我们的例子中是准确度。

import optuna
import torch
import torch.nn as nn
import torch.optim as optim
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

def build_model(params):

    in_features = 20

    return nn.Sequential(

        nn.Linear(in_features, params['n_unit']),
        nn.LeakyReLU(),
        nn.Linear(params['n_unit'], 2),
        nn.LeakyReLU()

    )

def train_and_evaluate(param, model):

    df = pd.read_csv('heart.csv')
    df = pd.get_dummies(df)

    train_data, val_data = train_test_split(df, test_size = 0.2, random_state = 42)
    train, val = Dataset(train_data), Dataset(val_data)

    train_dataloader = torch.utils.data.DataLoader(train, batch_size=2, shuffle=True)
    val_dataloader = torch.utils.data.DataLoader(val, batch_size=2)

    use_cuda = torch.cuda.is_available()
    device = torch.device("cuda" if use_cuda else "cpu")

    criterion = nn.CrossEntropyLoss()
    optimizer = getattr(optim, param['optimizer'])(model.parameters(), lr= param['learning_rate'])

    if use_cuda:

            model = model.cuda()
            criterion = criterion.cuda()

    for epoch_num in range(EPOCHS):

            total_acc_train = 0
            total_loss_train = 0

            for train_input, train_label in train_dataloader:

                train_label = train_label.to(device)
                train_input = train_input.to(device)

                output = model(train_input.float())

                batch_loss = criterion(output, train_label.long())
                total_loss_train += batch_loss.item()

                acc = (output.argmax(dim=1) == train_label).sum().item()
                total_acc_train += acc

                model.zero_grad()
                batch_loss.backward()
                optimizer.step()

            total_acc_val = 0
            total_loss_val = 0

            with torch.no_grad():

                for val_input, val_label in val_dataloader:

                    val_label = val_label.to(device)
                    val_input = val_input.to(device)

                    output = model(val_input.float())

                    batch_loss = criterion(output, val_label.long())
                    total_loss_val += batch_loss.item()

                    acc = (output.argmax(dim=1) == val_label).sum().item()
                    total_acc_val += acc

            accuracy = total_acc_val/len(val_data)

    return accuracy

def objective(trial):

     params = {
              'learning_rate': trial.suggest_loguniform('learning_rate', 1e-5, 1e-1),
              'optimizer': trial.suggest_categorical("optimizer", ["Adam", "RMSprop", "SGD"]),
              'n_unit': trial.suggest_int("n_unit", 4, 18)
              }

     model = build_model(params)

     accuracy = train_and_evaluate(params, model)

     return accuracy

运行超参数调优

我们已经创建了目标函数,我们已经定义了搜索空间,我们已经构建了模型和训练循环,现在我们准备好使用 Optuna 运行超参数调整。
要运行超参数调整,我们需要实例化一个study会话,调用optimize方法,并将我们的objective函数作为参数传递。

超参数调整过程完成后,我们可以通过访问best_trial方法来获取超参数的最佳组合,如下所示:

EPOCHS = 100

study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler())
study.optimize(objective, n_trials=100)
best_trial = study.best_trial

for key, value in best_trial.params.items():
    print("{}: {}".format(key, value))

以下是某项目的调参案例展示
optuna 自动化调参利器

optuna可视化

Optuna 提供了一项功能,使我们能够在完成后可视化调整过程的历史。我们现在将介绍其中的一些。
第一个可视化是每个训练步骤中每个实验的目标函数图(在我们的例子中是准确的)。

[En]

The first visualization is the objective function diagram (accuracy in our example) of each experiment in each training step.

optuna.visualization.plot_intermediate_values(study)

您还可以可视化优化历史:这种可视化有助于查看哪些实验是最好的,以及其他实验的客观价值如何与最好的进行比较。由于剪枝机制的原因,在具体的实验中有几个数据点缺失。

[En]

You can also visualize the optimization history: this visualization helps to see which experiments are the best and how the objective value of other experiments compares to the best. Due to the pruning mechanism, several data points are missing in specific experiments.

optuna.visualization.plot_optimization_history(study)

Optuna 还使我们能够绘制超参数的重要性,如下所示:

optuna.visualization.plot_param_importances(study)

optuna 自动化调参利器

optuna dashboard可视化

conda install -c conda-forge optuna-dashboard
pip install optuna-dashboard
study = optuna.create_study(study_name='test',direction="maximize",storage='sqlite:///db.sqlite3')

定义完后创建会话时,study_name指定了你的会话名称,direction为maximize或者minimize,最大或者最小,默认是最小,这里我们要让精确度最大,所以用maximize,storage定义了你的存储方式,这里我们用sqlite3,也可以用mysql等。

以上日志默认的保存位置在你当前的工作目录,会生成一个db.sqlite3的文件
optuna 自动化调参利器
再打开命令行或者anaconda-prompt,输入以下命令启动dashboard:

optuna-dashboard sqlite:///db.sqlite3

复制127.0.0.1:8080到你的浏览器里打开,就可以看到你的dashboard和study了:

如果指定服务器IP地址可使用

optuna-dashboard sqlite:///db.sqlite3 --host 0.0.0.0

复制IP:8080到你的浏览器里打开,同样可以看到你的dashboard和study
optuna 自动化调参利器
optuna 自动化调参利器
optuna 自动化调参利器
optuna 自动化调参利器
optuna 自动化调参利器

Original: https://blog.csdn.net/weixin_42788078/article/details/122984184
Author: James_Bobo
Title: optuna 自动化调参利器



相关阅读

Title: Pandas常用累计、同比、环比等统计方法实践案例

统计表中常常以本年累计、上年同期(累计)、当期(例如当月)完成、上月完成为统计数据,并进行同比、环比分析。如下月报统计表所示样例,本文将使用Python Pandas工具进行统计。
optuna 自动化调参利器
其中:

  • (本年)累计:是指本年1月到截止月份的合计数
  • (上年)同期(累计):是指去年1月到与本年累计所对应截止月份的合计数
  • 同比(增长率)=(本期数-同期数)/同期数*100%
  • 环比(增长率)=(本期数-上期数)/上期数*100%

注:这里的本期是指本月完成或当月完成,上期数是指上月完成。

示例数据:
optuna 自动化调参利器

注:为了演示方便,本案例数据源仅使用2年,且每年5个月的数据。

; 1. (本年)累计

在统计分析的发展中,按年和按月积累一些统计数据是相当常见的。对于数据,就是按规则逐行累计数据。

[En]

In the development of statistical analysis, it is quite common to accumulate some statistical data on an annual and monthly basis. For data, it is to accumulate data row by row according to the rules.

Pandas中的cumsum()函数可以实现按某时间维度累计需求。


import pandas as pd

df = pd.read_csv('data2021.csv')
cum_columns_name = ['cum_churncount','cum_newcount']
df[cum_columns_name] = df[['years','churncount','newcount']].groupby(['years']).cumsum()

注:其中分组'years'是指年度时间维度累计。

计算结果如下:
optuna 自动化调参利器

2. (上年)同期累计

对于(上年)同期累计,将直接取上一年度累计值的同月份数据。pandas DataFrame.shift()函数可以把数据移动指定的行数。
optuna 自动化调参利器
接续上列,读取同期数据。首先是把'yearmonth'上移五行,如上图所示得到新的DataFrame,通过'yearmonth'进行两表数据关联(左关联:左侧为原表,右侧为移动后的新表),实现去同期数据效果。

cum_columns_dict = {'cum_churncount':'cum_same_period_churncount',
                        'cum_newcount':'cum_same_period_newcount'}
df_cum_same_period = df[['cum_churncount','cum_newcount','yearmonth']].copy()
df_cum_same_period = df_cum_same_period.rename(columns=cum_columns_dict)

df_cum_same_period.loc[:,'yearmonth'] = df_cum_same_period['yearmonth'].shift(-5)

df = pd.merge(left=df,right=df_cum_same_period,on='yearmonth',how='left')

3. 上月(完成)

取上月的数据,使用pandas DataFrame.shift()函数把数据移动指定的行数。

接续上列,读取上期数据。(与取同期原理一样,略)

last_mnoth_columns_dict = {'churncount':'last_month_churncount',
                        'newcount':'last_month_newcount'}
df_last_month = df[['churncount','newcount','yearmonth']].copy()
df_last_month = df_last_month.rename(columns=last_mnoth_columns_dict)

df_last_month.loc[:,'yearmonth'] = df_last_month['yearmonth'].shift(-1)
df = pd.merge(left=df,right=df_last_month,on='yearmonth',how='left')

4. 同比(增长率)

计算同比涉及到除法,需要剔除除数为零的数据。

df.fillna(0,inplace=True)

df.loc[df['cum_same_period_churncount']!=0,'cum_churncount_rat'] = (df['cum_churncount']-df['cum_same_period_churncount'])/df['cum_same_period_churncount']
df.loc[df['cum_same_period_newcount']!=0,'cum_newcount_rat'] =  (df['cum_newcount']-df['cum_same_period_newcount'])/df['cum_same_period_newcount']
df[['yearmonth','cum_churncount','cum_newcount','cum_same_period_churncount','cum_same_period_newcount','cum_churncount_rat','cum_newcount_rat']]

optuna 自动化调参利器

5. 环比(增长率)


df.loc[df['last_month_churncount']!=0,'churncount_rat'] = (df['churncount']-df['last_month_churncount'])/df['last_month_churncount']
df.loc[df['last_month_newcount']!=0,'newcount_rat'] =  (df['newcount']-df['last_month_newcount'])/df['last_month_newcount']
df[['yearmonth','churncount','newcount','last_month_churncount','last_month_newcount','churncount_rat','newcount_rat']]

optuna 自动化调参利器

6. 总结

pandas做统计计算功能方法比较多,这里总结用到的技术有累计cumsum()函数、移动数据shift()函数、表合并关联merge()函数,以及通过loc条件修改数据。

Original: https://blog.csdn.net/xiaoyw/article/details/122979421
Author: 肖永威
Title: Pandas常用累计、同比、环比等统计方法实践案例

相关文章
语音识别ASR和NLP有什么区别? 人工智能

语音识别ASR和NLP有什么区别?

目录 背景 ASR是什么? NLP是什么? 最后 背景 语音识别中有两种技术分别是ASR和NLP,ASP是将语音识别转换成文本的技术,而NLP是自然语言,是理解和处理文本的过程,相当于解析器。 ASR...
Cross结构 【转载】 人工智能

Cross结构 【转载】

双塔式模型也称孪生网络、Representation-based,就是用一个编码器分别给两个文本编码出句向量,然后把两个向量融合过一个浅层的分类器;交互是也称Interaction-based,就是把...
nltk自然语言处理 人工智能

nltk自然语言处理

一些知识点 concordance concordance查找语料库中特定的单词的上下文, 检索词指定窗口大小的上下文。 concordance(word,width,lines),其中 width表...
YY0709|听觉报警信号要求及测试方法 人工智能

YY0709|听觉报警信号要求及测试方法

上一篇我们介绍了视觉报警信号的要求,今天主要来介绍一下听觉报警信号的要求。 查阅《YY0709-2009 医用电气设备 第1-8部分:安全通用要求 并列标准》,我们可以看到:视觉报警信号的要求主要集中...
什么是卷积(Convolution) 人工智能

什么是卷积(Convolution)

你好,这篇文章咱们讨论一下关于「什么是卷积(Convolution)」的事情... 卷积(Convolution)技术解析 卷积(Convolution)是深度学习领域中非常重要的一项技术,其在图像处...