Python案例如何用Scikit-learn做贝叶斯优化

wen python案例 1

本文目录导读:

Python案例如何用Scikit-learn做贝叶斯优化

  1. 安装必要的库
  2. 案例一:优化SVM超参数
  3. 案例二:优化随机森林参数
  4. 案例三:优化XGBoost参数(分类问题)
  5. 案例四:可视化优化过程
  6. 实用技巧和最佳实践

我来给你介绍几个使用Scikit-learn进行贝叶斯优化的实际案例,需要注意的是,Scikit-learn本身不直接提供贝叶斯优化功能,但我们可以结合scikit-optimize(skopt)库来实现。

安装必要的库

pip install scikit-learn scikit-optimize numpy matplotlib

案例一:优化SVM超参数

优化SVM的C和gamma参数,提高分类准确率。

import numpy as np
from sklearn.datasets import load_digits
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
from skopt import gp_minimize
from skopt.space import Real, Integer
from skopt.utils import use_named_args
# 加载数据集
digits = load_digits()
X, y = digits.data, digits.target
# 定义优化空间
space = [
    Real(1e-6, 1e+6, "log-uniform", name='C'),  # C参数范围
    Real(1e-6, 1e+1, "log-uniform", name='gamma'),  # gamma参数范围
    Integer(1, 5, name='degree')  # degree参数
]
# 定义目标函数
@use_named_args(space)
def objective(**params):
    svm = SVC(**params, random_state=42)
    # 使用5折交叉验证的负准确率作为目标值
    scores = cross_val_score(svm, X, y, cv=5, n_jobs=-1)
    return -np.mean(scores)  # 返回负值,因为gp_minimize寻找最小值
# 执行贝叶斯优化
result = gp_minimize(
    objective, 
    space, 
    n_calls=30,  # 迭代次数
    random_state=42,
    verbose=True
)
# 输出最佳参数
print("最佳参数:")
print(f"C = {result.x[0]:.4f}")
print(f"gamma = {result.x[1]:.4f}")
print(f"degree = {result.x[2]}")
print(f"最佳验证准确率 = {-result.fun:.4f}")

案例二:优化随机森林参数

优化随机森林的n_estimators和max_depth等参数。

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from skopt import forest_minimize
# 生成示例数据
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义搜索空间
space = [
    Integer(10, 500, name='n_estimators'),
    Integer(1, 20, name='max_depth'),
    Integer(2, 20, name='min_samples_split'),
    Integer(1, 20, name='min_samples_leaf'),
    Real(0.1, 1.0, name='max_features')
]
# 定义目标函数
@use_named_args(space)
def objective(**params):
    rf = RandomForestClassifier(**params, random_state=42, n_jobs=-1)
    scores = cross_val_score(rf, X_train, y_train, cv=5, n_jobs=-1)
    return -np.mean(scores)
# 执行优化
result = forest_minimize(
    objective,
    space,
    n_calls=40,
    random_state=42,
    verbose=True
)
# 使用最佳参数训练最终模型
best_rf = RandomForestClassifier(
    n_estimators=result.x[0],
    max_depth=result.x[1],
    min_samples_split=result.x[2],
    min_samples_leaf=result.x[3],
    max_features=result.x[4],
    random_state=42
)
best_rf.fit(X_train, y_train)
# 评估模型
test_score = best_rf.score(X_test, y_test)
print(f"最佳参数: {result.x}")
print(f"测试集准确率: {test_score:.4f}")

案例三:优化XGBoost参数(分类问题)

from xgboost import XGBClassifier
from sklearn.datasets import load_breast_cancer
# 加载数据
data = load_breast_cancer()
X, y = data.data, data.target
# 定义参数空间
space = [
    Integer(50, 500, name='n_estimators'),
    Integer(3, 10, name='max_depth'),
    Real(0.01, 0.3, "log-uniform", name='learning_rate'),
    Real(0.7, 1.0, name='subsample'),
    Real(0.7, 1.0, name='colsample_bytree'),
    Real(1e-8, 1.0, "log-uniform", name='reg_alpha'),
    Real(1e-8, 1.0, "log-uniform", name='reg_lambda')
]
# 目标函数
@use_named_args(space)
def objective(**params):
    xgb = XGBClassifier(**params, random_state=42, use_label_encoder=False, eval_metric='logloss')
    scores = cross_val_score(xgb, X, y, cv=5, n_jobs=-1)
    return -np.mean(scores)
# 执行优化
result = gp_minimize(
    objective,
    space,
    n_calls=50,
    random_state=42,
    verbose=True
)
print("最佳XGBoost参数:")
params_names = ['n_estimators', 'max_depth', 'learning_rate', 'subsample', 
                'colsample_bytree', 'reg_alpha', 'reg_lambda']
for name, value in zip(params_names, result.x):
    print(f"{name}: {value:.4f}")
print(f"最佳交叉验证分数: {-result.fun:.4f}")

案例四:可视化优化过程

import matplotlib.pyplot as plt
from skopt.plots import plot_convergence, plot_evaluations
# 假设我们已经有了优化结果
# 绘制收敛图
plot_convergence(result)"贝叶斯优化收敛过程")
plt.xlabel("迭代次数")
plt.ylabel("目标函数值")
plt.show()
# 查看参数评估分布
plot_evaluations(result)
plt.show()
# 创建部分依赖图
from skopt.plots import plot_objective
plot_objective(result)
plt.show()

实用技巧和最佳实践

from skopt import dummy_minimize
from skopt.callbacks import DeltaYStopper, VerboseCallback
# 1. 使用初始点加速优化
initial_points = [
    [1e-3, 1e-3, 3],  # C, gamma, degree
    [1e-1, 1e-1, 2],
    [1e+1, 1e-5, 4]
]
# 2. 添加早停条件和详细日志
callbacks = [
    DeltaYStopper(delta=0.001, n_best=5),  # 改进小于0.001时停止
    VerboseCallback(5)  # 每5次迭代输出一次日志
]
# 3. 使用多核并行计算(如果支持)
from skopt import Optimizer
opt = Optimizer(
    dimensions=space,
    base_estimator="GP",  # 高斯过程
    n_initial_points=10,
    initial_point_generator="random"
)
# 4. 带有约束条件的优化
from skopt.space import Categorical
# 定义条件空间
space_with_constraints = [
    Categorical(['linear', 'rbf', 'poly'], name='kernel'),
    Real(1e-6, 1e+6, "log-uniform", name='C'),
]
# 如果选择poly核,才优化degree参数
def kernel_constraint(params):
    if params[0] == 'poly':
        return params[2] <= 10  # degree <= 10
    return True
# 5. 保存和加载优化状态
import pickle
# 保存优化器状态
with open('optimizer_state.pkl', 'wb') as f:
    pickle.dump(result, f)
# 加载优化器状态
with open('optimizer_state.pkl', 'rb') as f:
    loaded_result = pickle.load(f)

贝叶斯优化相比网格搜索和随机搜索的优势:

  • 更高效:用更少的迭代找到更好的参数
  • 自适应:根据历史结果调整搜索策略
  • 处理复杂关系:能捕捉参数间的交互作用

在实际应用中,建议:

  1. 先用少量迭代(20-30次)快速探索
  2. 根据结果调整搜索空间
  3. 最后运行更多迭代(50-100次)进行精细优化
  4. 注意监控过拟合风险,使用交叉验证

这样就能高效地为你的机器学习模型找到最佳超参数配置。

抱歉,评论功能暂时关闭!