optuna是一个为机器学习,深度学习特别设计的自动超参数优化框架,具有脚本语言特性的用户API。因此,optuna的代码具有高度的模块特性,并且用户可以根据自己的希望动态构造超参数的搜索空间。另外,optuna也是kaggle比赛中十分热门的调参神器,在优秀方案中频繁出现。告别暴力的GridSearch调参。
项目地址:https://github.com/optuna/optuna

框架特点

  • 小巧轻量,通用且与平台无关
  • python形式的超参数空间搜索
  • 高效的优化算法
  • 写法简单,可以并行
  • 快速可视化

    安装

    Optuna 支持 Python 3.6 即以上版本
    pip 安装 Optuna
    1. pip install optuna
    conda 安装 Optuna
    1. conda install -c conda-forge optuna

    示例

    通常,基于树的模型的超参数可以分为 3步进行调参:
    1.树结构调整
    max_depth:树深度,如果不控制树的深度容易过拟合,一般设置为3-8。
    num_leaves:叶子结点个数,树模型为二叉树所以numleaves最大不应该超过_2^(maxdepth)。
    min_data_in_leaf:最小叶子节点数量,如果设置为50,那么数量到达50则树停止生长,所以这个值的大小和过拟合有关,其大小也和num_leaves有关,一般数据集体量越大设置的越大。
    2.准确性调整
    learning_rate:学习率
    n_estimators:树的数量
    这两个参数是经常调整的参数,一般需要去寻找n_estimatorslearning_rate的最佳组合。
    max_bin:这个参数也可以来提高准确率,但也存在过拟合风险。
    3.过拟合调整
    lambda_l1:L1正则
    lambda_l2:L2正则
    正则对过拟合有影响,比较难调,一般搜索范围设置在(0,100)。
    min_gain_to_split:分裂的最小增益,当计算增益不高时就不会继续分裂。
    bagging_fraction:训练每棵树的训练样本百分比,让每棵树好而不同。
    feature_fraction:每棵树时要采样的特征百分比,让每颗子树特征具有差异化,抵抗过拟合。

optuna将优化程序极简为三个简单步骤:目标函数(objective),单次试验(trial),和研究(study).

目标函数

  1. import numpy as np
  2. import pandas as pd
  3. from sklearn.metrics import accuracy_score,f1_score
  4. from sklearn.model_selection import StratifiedKFold
  5. import lightgbm as lgbm
  6. def objective(trial, data, target):
  7. X_train, X_test, y_train, y_test=train_test_split(data, target, train_size=0.3)# 数据集划分
  8. # 参数网格
  9. param_grid = {
  10. "n_estimators": trial.suggest_categorical("n_estimators", [10000]),
  11. "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.3),
  12. "num_leaves": trial.suggest_int("num_leaves", 20, 3000, step=20),
  13. "max_depth": trial.suggest_int("max_depth", 3, 12),
  14. "min_data_in_leaf": trial.suggest_int("min_data_in_leaf", 200, 10000, step=100),
  15. "lambda_l1": trial.suggest_int("lambda_l1", 0, 100, step=5),
  16. "lambda_l2": trial.suggest_int("lambda_l2", 0, 100, step=5),
  17. "min_gain_to_split": trial.suggest_float("min_gain_to_split", 0, 15),
  18. "bagging_fraction": trial.suggest_float("bagging_fraction", 0.2, 0.95, step=0.1),
  19. "bagging_freq": trial.suggest_categorical("bagging_freq", [1]),
  20. "feature_fraction": trial.suggest_float("feature_fraction", 0.2, 0.95, step=0.1),
  21. "random_state": 2021,
  22. }
  23. model = lgbm.LGBMClassifier(objective="gbdt", **param_grid)
  24. model.fit(
  25. X_train,
  26. y_train,
  27. eval_set=[(X_test, y_test)],
  28. eval_metric="multi_logloss",
  29. early_stopping_rounds=100,
  30. verbose=False
  31. )
  32. pred_lgb = model.predict(X_test)
  33. scores = f1_score(y_true=y_test, y_pred=pred_lgb,average='macro')
  34. return scores

单词试验 和 研究:

  1. n_trials=50
  2. train = pd.read_csv("train.csv")
  3. X,y = train.drop(["id","label"],axis=1),train["label"]
  4. study = optuna.create_study(direction="maximize", study_name="LGBM Classifier") # minimize
  5. study.optimize(func, n_trials=n_trials)

打印最佳参数:

  1. print(f"\tBest value (f1): {study.best_value:.5f}")
  2. print(f"\tBest params:")
  3. for key, value in study.best_params.items():
  4. print(f"\t\t{key}: {value}")

image.png
可视化

  1. optuna.visualization.plot_optimization_history(study)

image.png

  1. optuna.visualization.plot_parallel_coordinate(study)

image.png

  1. optuna.visualization.plot_param_importances(study)

image.png