Optuna是一款开源的调参工具,github star数量超过7k, 是目前最受欢迎的调参框架之一。
其主要优点如下:
1,Optuna拥有许多非常先进的调参算法(如贝叶斯优化,遗传算法采样等),这些算法往往可以在几十上百次的尝试过程中找到一个不可微问题的较优解。
2,通过配合optuna-dashboard,可以可视化整个调参过程,从各个方面加深对问题的理解,这是一个令人心动的特性!
公众号后台回复关键词:optuna,获取本文源代码和bilibili视频演示。
另外,Optuna还有如下一些非常实用的特性:
1,通过将搜索结果存储到sqlite或mysql、postgresql,Optuna支持断点续搜。
2,Optuna支持剪枝策略,提前结束一些中间返回结果较差的采样点从而加快搜索进程。
3,Optuna支持手动指定一些超参采样点,也可以添加已经计算过的采样点及其结果作为初始化样本点。
4,Optuna提供ask and tell 接口模式,无需显式定义目标函数,直接在循环中调优超参。
5,Optuna封装了非常丰富的基于plotly的可视化函数,便于分析调参结果。
6,通过将搜索结果存储到mysql或postgresql,并设置分布式模式,Optuna支持多机分布式搜索,通过并行方式加快搜索进程。
我们将首先展示一些非常实用的综合应用范例演示optuna在算法调优实践中的魔力。
然后展示一些optuna的基础特性范例详细讲解optuna的主要特性和API应用方法。
综合应用范例:
一,optuna对pytorch模型调参范例
二,optuna对tensorflow模型调参范例
三,optuna对多模型加权融合范例
基础特性范例:
四,单参数空间搜索范例
五,网格参数空间搜索范例
六,断点续搜范例
七,剪枝策略范例
八,各种调参可视化函数范例
九,手动添加超参数采样点范例
参考文档
optuna官方文档:https://optuna.readthedocs.io/en/stable/tutorial/index.html
optuna更多范例库:https://github.com/optuna/optuna-examples 【价值非常大,强烈建议参考】
!pip install optuna -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install optuna-dashboard -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install plotly -i https://pypi.tuna.tsinghua.edu.cn/simple
在后台异步执行打开 optuna-dashboard 可视化 监控页面,
然后浏览器中输入:http://localhost:8083/dashboard/ 查看监控页面,类似tensorboard
nohup optuna-dashboard --host 0.0.0.0 --port 8083 sqlite:///optuna.db &
#杀死 optuna-dashboard
#!ps aux|grep optuna-dashboard
#!kill -9 1161
import os
import optuna
from optuna.trial import TrialState
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch.utils.data
from torchvision import datasets
from torchvision import transforms
DEVICE = torch.device("cpu")
BATCHSIZE = 128
CLASSES = 10
DIR = os.getcwd()
EPOCHS = 10
N_TRAIN_EXAMPLES = BATCHSIZE * 30
N_VALID_EXAMPLES = BATCHSIZE * 10
def define_model(trial):
# We optimize the number of layers, hidden units and dropout ratio in each layer.
n_layers = trial.suggest_int("n_layers", 1, 3)
layers = []
in_features = 28 * 28
for i in range(n_layers):
out_features = trial.suggest_int("n_units_{}".format(i), 16, 64)
layers.append(nn.Linear(in_features, out_features))
layers.append(nn.ReLU())
p = trial.suggest_float("dropout_{}".format(i), 0.1, 0.5)
layers.append(nn.Dropout(p))
in_features = out_features
layers.append(nn.Linear(in_features, CLASSES))
layers.append(nn.LogSoftmax(dim=1))
return nn.Sequential(*layers)
def get_mnist():
# Load FashionMNIST dataset.
train_loader = torch.utils.data.DataLoader(
datasets.FashionMNIST(DIR, train=True, download=True, transform=transforms.ToTensor()),
batch_size=BATCHSIZE,
shuffle=True,
)
valid_loader = torch.utils.data.DataLoader(
datasets.FashionMNIST(DIR, train=False, transform=transforms.ToTensor()),
batch_size=BATCHSIZE,
shuffle=True,
)
return train_loader, valid_loader
def objective(trial):
# Generate the model.
model = define_model(trial).to(DEVICE)
# Generate the optimizers.
optimizer_name = trial.suggest_categorical("optimizer", ["Adam", "RMSprop", "SGD"])
lr = trial.suggest_float("lr", 1e-5, 1e-1, log=True)
optimizer = getattr(optim, optimizer_name)(model.parameters(), lr=lr)
# Get the FashionMNIST dataset.
train_loader, valid_loader = get_mnist()
# Training of the model.
for epoch in range(EPOCHS):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
# Limiting training data for faster epochs.
if batch_idx * BATCHSIZE >= N_TRAIN_EXAMPLES:
break
data, target = data.view(data.size(0), -1).to(DEVICE), target.to(DEVICE)
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
# Validation of the model.
model.eval()
correct = 0
with torch.no_grad():
for batch_idx, (data, target) in enumerate(valid_loader):
# Limiting validation data.
if batch_idx * BATCHSIZE >= N_VALID_EXAMPLES:
break
data, target = data.view(data.size(0), -1).to(DEVICE), target.to(DEVICE)
output = model(data)
# Get the index of the max log-probability.
pred = output.argmax(dim=1, keepdim=True)
correct += pred.eq(target.view_as(pred)).sum().item()
accuracy = correct / min(len(valid_loader.dataset), N_VALID_EXAMPLES)
#attention here
trial.report(accuracy, epoch)
# Handle pruning based on the intermediate value.
if trial.should_prune():
raise optuna.exceptions.TrialPruned()
return accuracy
if __name__ == "__main__":
storage_name = "sqlite:///optuna.db"
study = optuna.create_study(
pruner=optuna.pruners.MedianPruner(n_warmup_steps=3), direction="maximize",
study_name="fashion_mnist_torch", storage=storage_name,load_if_exists=True
)
study.optimize(objective, n_trials=20, timeout=1200)
best_params = study.best_params
best_value = study.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
打印结果如下
best_value = 0.83359375
best_params:
{'dropout_0': 0.19431468838501847, 'dropout_1': 0.3924836525263806, 'lr': 0.009735042569270273, 'n_layers': 2, 'n_units_0': 22, 'n_units_1': 52, 'optimizer': 'Adam'}
import optuna
from optuna.integration import TFKerasPruningCallback
from optuna.trial import TrialState
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.utils import to_categorical
N_TRAIN_EXAMPLES = 3000
N_VALID_EXAMPLES = 1000
BATCHSIZE = 128
CLASSES = 10
EPOCHS = 20
def create_model(trial):
# We optimize the number of layers, hidden units and dropout in each layer and
# the learning rate of RMSProp optimizer.
# We define our MLP.
n_layers = trial.suggest_int("n_layers", 1, 3)
model = keras.models.Sequential()
for i in range(n_layers):
num_hidden = trial.suggest_int("n_units_{}".format(i), 4, 64, log=True)
model.add(layers.Dense(num_hidden, activation="relu"))
dropout = trial.suggest_float("dropout_{}".format(i), 0.1, 0.5)
model.add(layers.Dropout(rate=dropout))
model.add(layers.Dense(CLASSES, activation="softmax"))
# We compile our model with a sampled learning rate.
learning_rate = trial.suggest_float("learning_rate", 1e-5, 1e-1, log=True)
model.compile(
loss="categorical_crossentropy",
optimizer=RMSprop(learning_rate=learning_rate),
metrics=["accuracy"],
)
return model
def objective(trial):
tf.keras.backend.clear_session()
# The data is split between train and validation sets.
(x_train, y_train), (x_valid, y_valid) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784)[:N_TRAIN_EXAMPLES].astype("float32") / 255
x_valid = x_valid.reshape(10000, 784)[:N_VALID_EXAMPLES].astype("float32") / 255
# Convert class vectors to binary class matrices.
y_train = to_categorical(y_train[:N_TRAIN_EXAMPLES], CLASSES)
y_valid = to_categorical(y_valid[:N_VALID_EXAMPLES], CLASSES)
# Generate our trial model.
model = create_model(trial)
# Fit the model on the training data.
# The KerasPruningCallback checks for pruning condition every epoch.
model.fit(
x_train,
y_train,
batch_size=BATCHSIZE,
callbacks=[TFKerasPruningCallback(trial, "val_accuracy")],
epochs=EPOCHS,
validation_data=(x_valid, y_valid),
verbose=0,
)
# Evaluate the model accuracy on the validation set.
score = model.evaluate(x_valid, y_valid, verbose=0)
return score[1]
if __name__ == "__main__":
storage_name = "sqlite:///optuna.db"
study = optuna.create_study(
pruner=optuna.pruners.MedianPruner(n_warmup_steps=10), direction="maximize",
study_name="mnist-tf", storage=storage_name,load_if_exists=True
)
study.optimize(objective, n_trials=20)
best_params = study.best_params
best_value = study.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
打印结果如下
best_value = 0.9079999923706055
best_params:
{'dropout_0': 0.22384888955958546, 'learning_rate': 0.0024974162743369756, 'n_layers': 1, 'n_units_0': 59}
多模型加权融合是一个常见的提升机器学习效果的方案。
但是各个模型的权重如何确定呢?
有些方案是使用线性回归或者逻辑回归模型进行学习,这种方案一般叫做stacking ensemble,但是这种方案一般是对可微的Loss进行优化的,无法直接对auc,acc等不可微的评价指标进行优化。
还有一些方案叫做greedy ensemble,可以直接对auc,acc等不可微的评价指标进行优化,是一种贪心的也是非常高效的一种方案。大家感兴趣的话可以去了解一下它的细节,但是因为是greedy的方式,有可能陷入局部最优值。
由于optuna是一个强大的不可微问题调优工具,我们可以使用它来寻找模型融合的权重,直接对auc,acc等不可微的评价指标进行优化,并且原则上说,不会陷入局部最优解,能够获得比greedy ensemble更好的融合权重。
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.metrics import roc_auc_score
# 一,准备数据
data,target = make_classification(n_samples=3000,n_features=20,
n_informative=12,n_redundant=4,n_repeated=0,n_classes=2,
n_clusters_per_class=4)
x_train_val, x_test, y_train_val, y_test = train_test_split(data, target)
x_train, x_valid, y_train, y_valid = train_test_split(x_train_val, y_train_val)
# 二,训练3个基础模型
tree = DecisionTreeClassifier()
mlp = MLPClassifier()
svc = SVC(probability=True)
mlp.fit(x_train,y_train)
tree.fit(x_train,y_train)
svc.fit(x_train,y_train)
# 三,评估模型效果
def get_val_auc(model):
probs = model.predict_proba(x_valid)[:,1]
val_auc = roc_auc_score(y_valid,probs)
return val_auc
def get_test_auc(model):
probs = model.predict_proba(x_test)[:,1]
val_auc = roc_auc_score(y_test,probs)
return val_auc
print("mlp_score:",get_test_auc(mlp))
print("tree_score:",get_test_auc(tree))
print("svc_score:",get_test_auc(svc))
# 四, optuna搜索权重
import optuna
preds_val = {name:(eval(name)).predict_proba(x_valid)[:,1] for name in ['mlp','tree','svc']}
def objective(trial):
weights = {name:trial.suggest_int(name, 1, 100) for name in ['mlp','tree','svc']}
probs = sum([weights[name]*preds_val[name] for name in ['mlp','tree','svc']])/sum(
[weights[name] for name in ['mlp','tree','svc']])
val_auc = roc_auc_score(y_valid,probs)
trial.report(val_auc, 0)
return val_auc
storage_name = "sqlite:///optuna.db"
study = optuna.create_study(
direction="maximize",
study_name="optuna_ensemble", storage=storage_name,load_if_exists=True
)
study.optimize(objective, n_trials=300, timeout=600)
best_params = study.best_params
best_value = study.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
best_value = 0.9763214030683023
best_params:
{'mlp': 93, 'svc': 81, 'tree': 1}
# 五, 评估模型融合效果
preds_test = {name:(eval(name)).predict_proba(x_test)[:,1] for name in ['mlp','tree','svc']}
def test_score(weights):
probs = sum([weights[name]*preds_test[name] for name in ['mlp','tree','svc']])/sum(
[weights[name] for name in ['mlp','tree','svc']])
test_auc = roc_auc_score(y_test,probs)
return test_auc
print('optuna_ensemble_score:',test_score(best_params))
optuna_ensemble_score: 0.955444558287796
比单模型的最优值svc的得分(0.9501)有些许提升。
以下的范例为基础特性范例讲解,方便大家了解optuna的各种特性以及API使用方法。
Optuna支持的调参算法主要包括以下这些:
optuna.samplers.GridSampler(网格搜索采样)
optuna.samplers.RandomSampler(随机搜索采样)
optuna.samplers.TPESampler(贝叶斯优化采样)
optuna.samplers.NSGAIISampler(遗传算法采样)
optuna.samplers.CmaEsSampler(协方差矩阵自适应演化策略采样,非常先进的优化算法)
此外,还可以用以下方法将部分超参固定,仅对其它一些参数进行超参优化。
optuna.samplers.PartialFixedSampler(部分参数固定采样算法)
可以在optuna.create_study时候用sampler参数指定。
如果不指定的话,一般在单目标优化算法中,使用的是optuna.samplers.TPESampler调参算法。
from IPython.display import display
import optuna
import numpy as np
import pandas as pd
import plotly.graph_objs as go
import plotly.express as px
optuna.logging.set_verbosity(optuna.logging.WARNING)
# 1, 定义目标函数
def objective(trial:optuna.trial.Trial):
x = trial.suggest_float("x", -10, 10)
return (x - 2) ** 2
# 2, 执行搜索过程
study = optuna.create_study(
sampler=optuna.samplers.CmaEsSampler(),
direction = "minimize",
study_name = "simple_task")
study.optimize(objective, n_trials=1000,show_progress_bar = True)
# 3, 获取最优超参
best_params = study.best_params
best_value = study.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
# 4, 绘制搜索过程
dftrials = study.trials_dataframe()[["number","value"]]
losses = dftrials["value"].tolist()
minlosses = [np.min(losses[0:i+1]) for i in range(len(losses))]
steps = range(len(losses))
dflog = pd.DataFrame({"steps":steps,"losses":losses,"minlosses":minlosses})
fig = px.scatter(data_frame=dflog,x = "steps",y = "losses", size_max = 500,log_y=True)
fig.update_traces(marker = dict(size = 20, color = "rgba(0,0,255,0.4)"),name = "all",showlegend = True)
fig.add_traces(go.Scatter(x=list(steps), y=minlosses, name = "best", showlegend=True))
fig.update_layout(legend=dict(orientation="v"))
fig.show()
best_value = 0.0013535850035239266
best_params:
{'x': 2.0367910995150176}
多个参数可以用字典表述成网格参数空间形式。
optuna支持各种各样的输入参数类型。常见的有以下一些
trail = optuna.trial.Trial
trail.suggest_categorical
trail.suggest_discrete_uniform
trail.suggest_float
trail.suggest_int
trail.suggest_loguniform
from IPython.display import display
import numpy as np
import matplotlib.pyplot as plt
import optuna
import plotly.graph_objs as go
import plotly.express as px
optuna.logging.set_verbosity(optuna.logging.WARNING)
# 1, 定义目标函数
def objective(trial:optuna.trial.Trial):
x = trial.suggest_float("x", -1, 1)
f = trial.suggest_categorical("f",['sin','sinh','cos','cosh'])
dic = {'sin':np.sin,'cos':np.cos,'sinh':np.sinh,'cosh':np.cosh}
fn = dic[f]
return fn(x)
# 2, 执行搜索过程
study = optuna.create_study(
sampler=optuna.samplers.TPESampler(seed=123),
direction = "minimize",
study_name = "grid_task")
study.optimize(objective, n_trials=100,show_progress_bar = True)
# 3, 获取最优超参
best_params = study.best_params
best_value = study.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
# 4, 绘制搜索过程
dftrials = study.trials_dataframe()[["number","value"]]
display(dftrials)
losses = dftrials["value"].tolist()
minlosses = [np.min(losses[0:i+1]) for i in range(len(losses))]
steps = range(len(losses))
dflog = pd.DataFrame({"steps":steps,"losses":losses,"minlosses":minlosses})
fig = px.scatter(data_frame=dflog,x = "steps",y = "losses", size_max = 500)
fig.update_traces(marker = dict(size = 20, color = "rgba(0,0,255,0.4)"),name = "all",showlegend = True)
fig.add_traces(go.Scatter(x=list(steps), y=minlosses, name = "best", showlegend=True))
fig.update_layout(legend=dict(orientation="v"))
fig.show()
有时候超参搜索过程中有可能中间机器会死掉,可以使用sqlite/mysql等存储方式存储搜索结果到数据库文件。
这样便可以读取历史搜索结果,继续搜索。
import sys
import optuna
optuna.logging.set_verbosity(optuna.logging.ERROR)
# 1, 定义目标函数
def objective(trial):
x = trial.suggest_float("x", -10, 10)
return (x - 2) ** 2
# 2, 执行搜索过程
study_name = "example-study"
storage_name = "sqlite:///{}.db".format(study_name)
#period0
study0 = optuna.create_study(study_name=study_name, storage=storage_name, load_if_exists=True)
study0.optimize(objective, n_trials=10)
#period1
study1 = optuna.create_study(study_name=study_name, storage=storage_name, load_if_exists=True)
study1.optimize(objective, n_trials=10)
#period2
study2 = optuna.create_study(study_name=study_name, storage=storage_name, load_if_exists=True)
dftrials = study2.trials_dataframe(attrs=("number", "value", "params", "state"))
# 3, 获取最优超参
best_params = study2.best_params
best_value = study2.best_value
print("\n\nbest_value = "+str(best_value))
print("best_params:")
print(best_params)
display(dftrials)
# 4, 绘制搜索过程
fig = optuna.visualization.plot_optimization_history(study2)
#fig.layout.yaxis.type = 'log'
fig.update_layout({"yaxis.type":"log"})
optuna支持多种剪枝策略,如果某个超参采样点返回的中间结果和之前采样点相比表现得没有希望,optuna可以提前结束这个采样点的训练,从而节约时间。
optuna.pruners.HyperbandPruner: pruner refers to http://www.jmlr.org/papers/volume18/16-558/16-558.pdf
optuna.pruners.MedianPruner: Prune if the trial's best intermediate result is worse than median of intermediate results of previous trials at the same step.
optuna.pruners.ThresholdPruner: Pruner to detect outlying metrics of the trials
import optuna
from optuna.visualization import plot_optimization_history
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
optuna.logging.set_verbosity(optuna.logging.ERROR)
def objective(trial):
iris = load_iris()
data,target = iris["data"],iris["target"]
x_train, x_valid, y_train, y_valid = train_test_split(data, target)
classes = list(set(target))
clf = MLPClassifier(
hidden_layer_sizes=tuple(
[trial.suggest_int("n_units_l{}".format(i), 32, 64) for i in range(3)]
),
learning_rate_init=trial.suggest_float("lr_init", 1e-5, 1e-1, log=True),
)
for step in range(100):
clf.partial_fit(x_train, y_train, classes=classes)
value = clf.score(x_valid, y_valid)
# Report intermediate objective value.
trial.report(value, step)
# Handle pruning based on the intermediate value.
if trial.should_prune():
raise optuna.TrialPruned()
return value
if __name__ == "__main__":
study = optuna.create_study(direction="maximize", pruner=optuna.pruners.MedianPruner())
study.optimize(objective, n_trials=100, timeout=600)
plot_optimization_history(study).show()
import optuna
from optuna.visualization import plot_contour
from optuna.visualization import plot_intermediate_values
from optuna.visualization import plot_optimization_history
from optuna.visualization import plot_parallel_coordinate
from optuna.visualization import plot_param_importances
from optuna.visualization import plot_slice
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
optuna.logging.set_verbosity(optuna.logging.ERROR)
def objective(trial):
iris = load_iris()
data,target = iris["data"],iris["target"]
x_train, x_valid, y_train, y_valid = train_test_split(data, target)
classes = list(set(target))
clf = MLPClassifier(
hidden_layer_sizes=tuple(
[trial.suggest_int("n_units_l{}".format(i), 32, 64) for i in range(3)]
),
learning_rate_init=trial.suggest_float("lr_init", 1e-5, 1e-1, log=True),
)
for step in range(100):
clf.partial_fit(x_train, y_train, classes=classes)
value = clf.score(x_valid, y_valid)
# Report intermediate objective value.
trial.report(value, step)
# Handle pruning based on the intermediate value.
if trial.should_prune():
raise optuna.TrialPruned()
return value
if __name__ == "__main__":
study = optuna.create_study(direction="maximize", pruner=optuna.pruners.MedianPruner())
study.optimize(objective, n_trials=100, timeout=600)
# Visualize the optimization history.
plot_optimization_history(study).show()
# Visualize the learning curves of the trials.
plot_intermediate_values(study).show()
# Visualize high-dimensional parameter relationships.
plot_parallel_coordinate(study).show()
# Select parameters to visualize.
plot_parallel_coordinate(study, params=["lr_init", "n_units_l0"]).show()
# Visualize hyperparameter relationships.
plot_contour(study).show()
# Select parameters to visualize.
plot_contour(study, params=["n_units_l0", "n_units_l1"]).show()
# Visualize individual hyperparameters.
plot_slice(study).show()
# Select parameter
# Visualize parameter importances.
plot_param_importances(study).show()
有时候,我们在使用特定的采样算法之前,想尝试一些人工指定的超参采样点,在Optuna中我们可以用
study.enqueue_trial 将这些人工指定超参采样点推入测试队列。
另外,如果我们已经手动执行了一些超参采样点,并获得了结果,我们可以用 study.add_trail的方法
将这些结果添加到已评估的超参采样点列表中。后续的超参数采样将会考虑这些采样点。
1,指定手工采样点
import lightgbm as lgb
import numpy as np
import sklearn.datasets
import sklearn.metrics
from sklearn.model_selection import train_test_split
import optuna
def objective(trial):
data, target = sklearn.datasets.load_breast_cancer(return_X_y=True)
train_x, valid_x, train_y, valid_y = train_test_split(data, target, test_size=0.25)
dtrain = lgb.Dataset(train_x, label=train_y)
dvalid = lgb.Dataset(valid_x, label=valid_y)
param = {
"objective": "binary",
"metric": "auc",
"verbosity": -1,
"boosting_type": "gbdt",
"bagging_fraction": min(trial.suggest_float("bagging_fraction", 0.4, 1.0 + 1e-12), 1),
"bagging_freq": trial.suggest_int("bagging_freq", 0, 7),
"min_child_samples": trial.suggest_int("min_child_samples", 5, 100),
}
# Add a callback for pruning.
pruning_callback = optuna.integration.LightGBMPruningCallback(trial, "auc")
gbm = lgb.train(
param, dtrain, valid_sets=[dvalid], verbose_eval=False, callbacks=[pruning_callback]
)
preds = gbm.predict(valid_x)
pred_labels = np.rint(preds)
accuracy = sklearn.metrics.accuracy_score(valid_y, pred_labels)
return accuracy
study = optuna.create_study(direction="maximize", pruner=optuna.pruners.MedianPruner())
study.enqueue_trial(
{
"bagging_fraction": 1.0,
"bagging_freq": 0,
"min_child_samples": 20,
}
)
study.enqueue_trial(
{
"bagging_fraction": 0.75,
"bagging_freq": 5,
"min_child_samples": 20,
}
)
import logging
import sys
# Add stream handler of stdout to show the messages to see Optuna works expectedly.
optuna.logging.get_logger("optuna").addHandler(logging.StreamHandler(sys.stdout))
study.optimize(objective, n_trials=100, timeout=600)
2,添加已评估采样点
import lightgbm as lgb
import numpy as np
import sklearn.datasets
import sklearn.metrics
from sklearn.model_selection import train_test_split
import optuna
def objective(trial):
data, target = sklearn.datasets.load_breast_cancer(return_X_y=True)
train_x, valid_x, train_y, valid_y = train_test_split(data, target, test_size=0.25)
dtrain = lgb.Dataset(train_x, label=train_y)
dvalid = lgb.Dataset(valid_x, label=valid_y)
param = {
"objective": "binary",
"metric": "auc",
"verbosity": -1,
"boosting_type": "gbdt",
"bagging_fraction": min(trial.suggest_float("bagging_fraction", 0.4, 1.0 + 1e-12), 1),
"bagging_freq": trial.suggest_int("bagging_freq", 0, 7),
"min_child_samples": trial.suggest_int("min_child_samples", 5, 100),
}
# Add a callback for pruning.
pruning_callback = optuna.integration.LightGBMPruningCallback(trial, "auc")
gbm = lgb.train(
param, dtrain, valid_sets=[dvalid], verbose_eval=False, callbacks=[pruning_callback]
)
preds = gbm.predict(valid_x)
pred_labels = np.rint(preds)
accuracy = sklearn.metrics.accuracy_score(valid_y, pred_labels)
return accuracy
study = optuna.create_study(direction="maximize", pruner=optuna.pruners.MedianPruner())
study.add_trial(
optuna.trial.create_trial(
params={
"bagging_fraction": 1.0,
"bagging_freq": 0,
"min_child_samples": 20,
},
distributions={
"bagging_fraction": optuna.distributions.UniformDistribution(0.4, 1.0 + 1e-12),
"bagging_freq": optuna.distributions.IntUniformDistribution(0, 7),
"min_child_samples": optuna.distributions.IntUniformDistribution(5, 100),
},
value=0.94,
)
)
study.add_trial(
optuna.trial.create_trial(
params={
"bagging_fraction": 0.75,
"bagging_freq": 5,
"min_child_samples": 20,
},
distributions={
"bagging_fraction": optuna.distributions.UniformDistribution(0.4, 1.0 + 1e-12),
"bagging_freq": optuna.distributions.IntUniformDistribution(0, 7),
"min_child_samples": optuna.distributions.IntUniformDistribution(5, 100),
},
value=0.95,
)
)
study.optimize(objective, n_trials=100, timeout=600)