《sklearn机器学习》——调整估计器的超参数

发布于:2025-09-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

GridSearchCV 详解:网格搜索与超参数优化

GridSearchCVscikit-learn 中用于超参数调优的核心工具之一。它通过系统地遍历用户指定的参数组合,使用交叉验证评估每种组合的性能,最终选择并返回表现最优的参数配置。这种方法被称为网格搜索(Grid Search),是一种穷举式的搜索策略。


1. 核心原理

GridSearchCV 的工作流程如下:

  1. 定义参数搜索空间:通过 param_grid 参数指定一组候选超参数及其取值范围。
  2. 生成所有参数组合:对 param_grid 中的每个字典,计算其内部参数的笛卡尔积(交叉乘积),生成所有可能的参数组合。
  3. 交叉验证评估:对每一种参数组合,使用交叉验证(CV)在训练集上评估模型性能(如准确率、F1 分数等)。
  4. 选择最优模型:根据 CV 的平均得分,选择表现最好的参数组合。
  5. 训练最终模型:使用最优参数在整个训练集上重新训练一个最终模型。
  6. 提供接口GridSearchCV 实例本身实现了与基础估计器相同的 API(如 fit, predict, score),可像普通模型一样使用。

2. param_grid 参数详解

param_grid 是一个列表,其中每个元素是一个字典。每个字典代表一个独立的“参数网格”,用于探索某一类模型配置。

示例解析

param_grid = [
    {'C': [1, 10, 100, 1000], 'kernel': ['linear']},
    {'C': [1, 10, 100, 1000], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']},
]

网格 1:线性核 SVM
‘kernel’: [‘linear’]:固定使用线性核。
‘C’: [1, 10, 100, 1000]:正则化参数 C 的候选值。
组合数:4(C 的 4 个值)× 1(kernel 的 1 个值) = 4 种组合
网格 2:RBF 核 SVM
‘kernel’: [‘rbf’]:固定使用径向基函数(RBF)核。
‘C’: [1, 10, 100, 1000]:C 的候选值。
‘gamma’: [0.001, 0.0001]:RBF 核的 gamma 参数(控制单个样本的影响范围)。
组合数:4(C)× 2(gamma)× 1(kernel) = 8 种组合
总计
GridSearchCV 将评估 4 + 8 = 12 个不同的参数组合。
每个组合都会进行 k 折交叉验证(如 5 折),因此总共需要训练 12 × 5 = 60 个模型。

3.完整使用流程

from sklearn import svm, datasets
from sklearn.model_selection import GridSearchCV, train_test_split

# 加载数据
iris = datasets.load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)

# 定义参数网格
param_grid = [
    {'C': [0.1, 1, 10, 100], 'kernel': ['linear']},
    {'C': [0.1, 1, 10, 100], 'gamma': [1, 0.1, 0.01, 0.001], 'kernel': ['rbf']},
]

# 创建 GridSearchCV 对象
grid_search = GridSearchCV(
    estimator=svm.SVC(),        # 要调优的估计器
    param_grid=param_grid,      # 参数网格
    cv=5,                       # 5 折交叉验证
    scoring='accuracy',         # 评估指标
    n_jobs=-1,                  # 使用所有 CPU 核心并行计算
    verbose=1                   # 输出搜索进度
)

# 在训练集上拟合(开始搜索)
grid_search.fit(X_train, y_train)

# 输出结果
print("最佳参数:", grid_search.best_params_)
print("最佳交叉验证得分:", grid_search.best_score_)

# 直接用于预测(自动使用最优模型)
y_pred = grid_search.predict(X_test)
print("测试集得分:", grid_search.score(X_test, y_test))

4.GridSearchCV 的关键属性(拟合后可用)

属性 说明
best_estimator_ 通过搜索找到的最佳模型(已训练)
best_params_ 最佳参数组合(字典形式)
best_score_ 最佳参数在交叉验证上的平均得分
cv_results_ 详细结果字典,包含每种参数组合的得分、标准差、训练时间等
n_splits_ 实际使用的交叉验证折数

5.优缺点分析

优点
简单直观:易于理解和实现。
保证找到指定范围内的最优解:在给定的参数网格中进行穷举,不遗漏任何组合。
结果可复现:固定随机种子后,结果稳定。
缺点
计算成本高:参数数量和候选值增加时,组合数呈指数增长(“维度灾难”)。
依赖于候选值范围:如果最优参数不在指定范围内,则无法找到。
离散搜索:只能在预设的离散值中选择,可能错过两个候选值之间的更优解。


RandomizedSearchCV:随机搜索超参数优化

尽管网格搜索(GridSearchCV)是最直观和广泛使用的超参数优化方法,但在许多场景下,随机搜索(Random Search) 表现出更优的效率和性能。scikit-learn 提供了 RandomizedSearchCV 类来实现这一策略。
与穷举所有参数组合的网格搜索不同,RandomizedSearchCV 从参数的概率分布中随机采样指定数量的候选组合,并通过交叉验证评估其性能,最终选择最优者。


1. 核心优势

相比 GridSearchCVRandomizedSearchCV 具有两大显著优势:

✅ 优势 1:运行成本与参数维度解耦

  • 网格搜索:总评估次数 = C 的候选数 × gamma 的候选数 × ...,随参数数量呈指数增长
  • 随机搜索:总评估次数由 n_iter 参数直接控制(如 100 次),与参数个数和每个参数的候选值数量无关
  • 意义:可以轻松探索高维参数空间(如 10 个参数),而网格搜索在高维下会变得计算不可行。

✅ 优势 2:易于扩展和迭代

  • 添加新的超参数不会显著增加计算负担(只要 n_iter 不变)。
  • 可以先用较小的 n_iter 快速探索,再逐步增加预算进行精细化搜索。
  • 对于不重要的参数,即使采样范围较宽,随机搜索也能高效地“跳过”低性能区域。

理论支持:Bergstra & Bengio (2012) 的研究表明,在相同计算预算下,随机搜索比网格搜索更可能找到接近最优的参数组合,尤其当性能主要由少数关键参数决定时。


2. param_distributions 参数详解

RandomizedSearchCV 使用 param_distributions 参数(字典)定义参数的采样方式,其结构与 GridSearchCVparam_grid 类似,但语义不同:

  • 列表:如 ['rbf', 'linear'],表示从这些离散值中均匀采样
  • 分布对象:如 scipy.stats.expon,表示从该连续分布中采样。

示例解析

from scipy.stats import expon
from sklearn.utils.fixes import loguniform

param_distributions = {
    'C': expon(scale=100),           # C ~ 指数分布,scale=100
    'gamma': expon(scale=0.1),       # gamma ~ 指数分布,scale=0.1
    'kernel': ['rbf'],               # 固定为 'rbf'
    'class_weight': ['balanced', None]  # 从两个值中均匀采样
}

C 和 gamma 从指数分布中采样,更倾向于生成较小的值(符合 SVM 的常见调优经验)。
kernel 固定为 ‘rbf’。
class_weight 在 ‘balanced’ 和 None 之间二选一。

3. 连续对数均匀分布:loguniform

对于像 C、gamma 这类通常在对数尺度上调整的超参数,使用对数均匀分布(log-uniform)比线性均匀分布更合理。

为什么使用 loguniform?

  • 参数如 C=1, C=10, C=100 在性能上的差异通常是乘法性的,而非加法性。
  • 在 [1, 1000] 上均匀采样,大部分样本会落在 [100, 1000] 区间,而 [1, 10] 区间样本稀少。
  • loguniform 在对数尺度上均匀采样,确保 C=1~10, 10~100, 100~1000 的采样概率相等。
    使用方法
python
深色版本
from sklearn.utils.fixes import loguniform

param_distributions = {
    'C': loguniform(1e0, 1e3),      # C ∈ [1, 1000] 对数均匀分布
    'gamma': loguniform(1e-4, 1e-3), # gamma ∈ [0.0001, 0.001] 对数均匀分布
    'kernel': ['rbf'],
    'class_weight': ['balanced', None]
}

注意:loguniform(a, b) 是 scipy.stats.reciprocal(a, b) 的别名,要求 a < b。

4. 自定义采样分布

RandomizedSearchCV 的灵活性在于,任何具有 rvs 方法的对象都可以作为分布。

示例:使用均匀分布

python
深色版本
from scipy.stats import uniform

param_distributions = {
    'C': uniform(0.1, 1000),  # 在 [0.1, 1000.1) 区间均匀采样
    'gamma': uniform(0.0001, 0.001) # 在 [0.0001, 0.0010001) 区间均匀采样
}

示例:使用整数均匀分布

python
深色版本
from scipy.stats import randint

param_distributions = {
    'n_estimators': randint(10, 200),     # 生成 [10, 200) 的整数
    'max_depth': [3, 5, 7, 10, None]     # 或使用列表
}

5. 完整使用示例

python
深色版本
from sklearn import svm, datasets
from sklearn.model_selection import RandomizedSearchCV, train_test_split
from sklearn.utils.fixes import loguniform
import numpy as np

# 加载数据
iris = datasets.load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)

# 定义参数分布
param_distributions = {
    'C': loguniform(1e0, 1e3),
    'gamma': loguniform(1e-4, 1e-1),
    'kernel': ['rbf', 'poly'],
    'degree': [2, 3, 4]  # 仅对 poly 核有效
}

# 创建 RandomizedSearchCV 对象
random_search = RandomizedSearchCV(
    estimator=svm.SVC(),           # 基础估计器
    param_distributions=param_distributions,  # 参数分布
    n_iter=100,                    # 采样 100 个候选组合
    cv=5,                          # 5 折交叉验证
    scoring='accuracy',            # 评估指标
    n_jobs=-1,                     # 并行计算
    random_state=42,               # 确保结果可复现
    verbose=1
)

# 执行搜索
random_search.fit(X_train, y_train)

# 输出结果
print("最佳参数:", random_search.best_params_)
print("最佳得分:", random_search.best_score_)
print("测试集得分:", random_search.score(X_test, y_test))

6. RandomizedSearchCV vs GridSearchCV 对比

特性 GridSearchCV RandomizedSearchCV
搜索策略 穷举所有组合 随机采样 n_iter
计算成本 随参数指数增长 n_iter 控制
高维适用性
找到全局最优 在网格内保证 概率性,随 n_iter 增加而提高
参数指定 列表(离散) 列表或分布(连续/离散)
推荐场景 参数少(≤3),范围明确 参数多,探索性强,预算有限

7. 使用建议

  • 优先使用 loguniform:对于学习率、正则化系数等对数尺度敏感的参数。
  • 合理设置 n_iter:通常 n_iter=50~200 即可获得不错的结果,可根据计算资源调整。
  • 结合领域知识:为关键参数选择合理的分布(如指数分布、正态分布)。
  • 可复现性:务必设置 random_state
  • 后续精细化:可先用 RandomizedSearchCV 定位大致最优区域,再用 GridSearchCV 在小范围内精细搜索。

Scikit-learn 超参数搜索高级技巧:从多指标评估到并行优化

在使用 GridSearchCVRandomizedSearchCV 进行模型调优时,掌握一些高级技巧可以显著提升调参效率和模型性能。本文将详细介绍目标度量选择、多指标评估、复合估计器调参、开发/评估分离、并行计算以及容错机制等实用技巧,帮助你构建更鲁棒、更高效的机器学习流程。


1. 指定目标评估指标(scoring 参数)

默认情况下,GridSearchCVRandomizedSearchCV 使用估计器自带的 score 方法进行评估:

  • 分类任务:使用 accuracy_score(准确率)
  • 回归任务:使用 r2_score(R² 决定系数)

但在实际应用中,默认指标往往不足以反映模型的真实性能

📌 为什么需要自定义评分函数?

类别不平衡分类为例:

  • 假设正负样本比例为 1:99。
  • 一个“懒惰”模型对所有样本都预测为负类,其准确率可达 99%。
  • 但该模型毫无实用价值,因为它完全无法识别正类。

此时,准确率(Accuracy)就是一个信息不足的指标。我们更应关注:

  • F1 分数(F1-score):平衡精确率与召回率
  • AUC-ROC:衡量分类器整体性能
  • Precision/Recall:针对特定业务需求

✅ 如何指定自定义评分?

通过 scoring 参数传入预定义的字符串或自定义评分函数:

from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer, f1_score
from sklearn.svm import SVC

# 方法1:使用预定义字符串
grid_search = GridSearchCV(
    SVC(),
    param_grid={'C': [0.1, 1, 10]},
    scoring='f1_macro',  # 适用于多分类
    cv=5
)

# 方法2:使用 make_scorer 创建自定义评分器
f1_scorer = make_scorer(f1_score, average='weighted')
grid_search = GridSearchCV(
    SVC(),
    param_grid={'C': [0.1, 1, 10]},
    scoring=f1_scorer,
    cv=5
)

2. 多指标评估:全面评估模型性能

有时我们需要同时关注多个指标(如准确率、召回率、AUC),scikit-learn 支持多指标评估。

✅ 如何启用多指标评估?
将 scoring 设置为列表或字典:

python
深色版本
# 方法1:列表形式(使用预定义名称)
scoring = ['accuracy', 'precision', 'recall', 'f1']

# 方法2:字典形式(可自定义名称)
scoring = {
    'acc': 'accuracy',
    'prec': 'precision_macro',
    'rec': 'recall_macro',
    'f1': 'f1_macro'
}

grid_search = GridSearchCV(
    estimator=SVC(),
    param_grid={'C': [0.1, 1, 10]},
    scoring=scoring,
    cv=5,
    refit='f1'  # 必须指定一个指标用于 refit
)

⚠️ 关键参数:refit
当使用多指标时,必须设置 refit 参数:

  • refit=‘f1’:选择 F1 分数最高的参数组合,并在整个训练集上重新训练最终模型。
  • refit=False:不重新训练模型,此时无法使用 best_estimator_ 和 predict 方法。
  • refit=None:会抛出错误(必须显式指定)。

🔍 查看多指标结果

python
深色版本
grid_search.fit(X_train, y_train)

# 获取最佳参数
print("最佳参数:", grid_search.best_params_)
print("最佳 F1 分数:", grid_search.best_score_)

# 查看所有指标的详细结果
import pandas as pd
results = pd.DataFrame(grid_search.cv_results_)
print(results[['params', 'mean_test_acc', 'mean_test_prec', 'mean_test_rec', 'mean_test_f1']])

3. 复合估计器调参:Pipeline 与嵌套参数

现代机器学习流程常使用 Pipeline、ColumnTransformer 等复合估计器。幸运的是,GridSearchCV 支持对这些嵌套结构进行调参。

✅ 使用 __ 语法访问嵌套参数

python
深色版本
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.calibration import CalibratedClassifierCV
from sklearn.ensemble import RandomForestClassifier

# 构建嵌套模型
calibrated_forest = CalibratedClassifierCV(
    base_estimator=RandomForestClassifier(n_estimators=10)
)

pipe = Pipeline([
    ('select', SelectKBest(score_func=f_classif)),  # 特征选择
    ('model', calibrated_forest)                    # 校准后的随机森林
])

# 定义参数网格:使用 __ 分隔层级
param_grid = {
    'select__k': [5, 10, 15],  # SelectKBest 的 k 参数
    'model__base_estimator__max_depth': [3, 5, 7],  # 随机森林的最大深度
    'model__method': ['sigmoid', 'isotonic']  # 校准方法
}

# 执行网格搜索
grid_search = GridSearchCV(pipe, param_grid, cv=5, scoring='f1')
grid_search.fit(X_train, y_train)

📌 命名规则说明

  • select__k:select 是 Pipeline 中步骤的名称,k 是 SelectKBest 的参数。
  • model__base_estimator__max_depth:model → CalibratedClassifierCV → base_estimator(即 RandomForestClassifier)→ max_depth。

4. 模型选择:开发集与评估集分离

为避免评估偏差,推荐将数据划分为三部分:

训练集:用于模型训练。
开发集(验证集):用于超参数搜索(GridSearchCV 使用)。
测试集(评估集):用于最终评估模型性能。
✅ 正确做法:两阶段划分

python
深色版本
from sklearn.model_selection import train_test_split

# 第1步:划分开发集(用于调参)和评估集(最终测试)
X_dev, X_eval, y_dev, y_eval = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 第2步:在开发集上进行网格搜索
grid_search = GridSearchCV(SVC(), param_grid={'C': [0.1, 1, 10]}, cv=5)
grid_search.fit(X_dev, y_dev)

# 第3步:在独立的评估集上测试最终模型
final_score = grid_search.score(X_eval, y_eval)
print("最终评估得分:", final_score)

💡 为什么重要?
如果用同一份数据既调参又评估,会导致评估结果过于乐观,因为模型已经“见过”测试数据的分布。

5. 并行计算:加速搜索过程

GridSearchCV 和 RandomizedSearchCV 的每个参数组合都是独立评估的,非常适合并行化。

✅ 启用并行计算
设置 n_jobs 参数:

python
深色版本
grid_search = GridSearchCV(
    estimator=SVC(),
    param_grid={'C': [0.1, 1, 10, 100]},
    cv=5,
    n_jobs=-1,      # 使用所有 CPU 核心
    verbose=1       # 显示进度
)
n_jobs=1:单进程(默认)
n_jobs=4:使用 4 个核心
n_jobs=-1:使用所有可用核心

⚠️ 注意:

并行会增加内存消耗(每个进程复制数据)。
对于小数据集或简单模型,开启并行可能因进程开销而变慢。

6. 对失败的鲁棒性:error_score 参数

某些参数组合可能导致模型训练失败(如 SVM 中 gamma=0 或 learning_rate 过大导致梯度爆炸)。

默认情况下,一次失败会导致整个搜索中断。

✅ 启用容错机制
使用 error_score 参数处理异常:

python
深色版本
grid_search = GridSearchCV(
    estimator=SVC(),
    param_grid={'C': [0.1, 1, 10], 'gamma': [0.0, 0.1]},  # gamma=0 会失败
    cv=5,
    error_score=np.nan  # 或 error_score=0
)
error_score=np.nan:将失败的 CV 折得分设为 NaN,该参数组合的平均得分也会是 NaN。
error_score=0:设为 0,通常用于最大化目标(如准确率)。
搜索完成后,GridSearchCV 会跳过包含 NaN 或极低分的组合。

暴力参数搜索的替代方法:高效模型选择策略

在机器学习中,GridSearchCVRandomizedSearchCV 是常用的超参数调优工具,但它们属于“暴力搜索”——需要为每个参数组合独立训练模型,计算成本高昂。

幸运的是,scikit-learn 提供了多种更高效的替代方法,能够在不进行完整交叉验证的情况下自动选择最优超参数。这些方法主要包括:

  1. 模型特定的交叉验证(Model-specific CV)
  2. 基于信息准则的模型选择(AIC/BIC)
  3. 袋外估计(Out-of-Bag Estimation)

下面详细介绍这三种高效策略。


1. 模型特定的交叉验证:利用正则化路径

某些线性模型具有一个关键特性:它们可以在一次拟合过程中计算出多个正则化参数(如 alpha)对应的模型解,这条轨迹称为正则化路径(Regularization Path)

这意味着我们可以在几乎不增加计算成本的情况下,评估大量 alpha 值的性能,从而高效地进行交叉验证。

✅ 适用场景

  • 主要用于带正则化的线性模型
  • 正则化参数(如 alphaC)是主要调优目标。

✅ 核心优势

  • 速度快:相比对每个 alpha 单独训练,利用正则化路径的 CV 速度快数十倍。
  • 精度高:可以密集地搜索 alpha 空间。

📌 支持的模型列表

模型 说明
RidgeCV 岭回归(L2 正则化)的内置交叉验证
LassoCV Lasso 回归(L1 正则化)的内置交叉验证
ElasticNetCV Elastic Net(L1+L2)的内置交叉验证
LogisticRegressionCV 逻辑回归的内置交叉验证(支持多分类)
LarsCV, LassoLarsCV 基于最小角回归(LARS)算法的高效路径计算
MultiTaskLassoCV, MultiTaskElasticNetCV 多任务学习版本的 Lasso/ElasticNet

✅ 使用示例:RidgeCV

from sklearn.linear_model import RidgeCV
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split

# 生成数据
X, y = make_regression(n_samples=1000, n_features=20, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义 alpha 候选值
alphas = [0.1, 1.0, 10.0, 100.0]

# 使用 RidgeCV 进行自动调参
ridge_cv = RidgeCV(
    alphas=alphas,           # 候选 alpha 值
    cv=5,                    # 5 折交叉验证
    scoring='neg_mean_squared_error'  # 评估指标
)

# 拟合并自动选择最佳 alpha
ridge_cv.fit(X_train, y_train)

print("最佳 alpha:", ridge_cv.alpha_)
print("交叉验证得分:", ridge_cv.best_score_)
print("测试集 R² 得分:", ridge_cv.score(X_test, y_test))

2. 基于信息准则的模型选择:AIC 与 BIC

对于某些模型,可以在单次拟合后,使用信息准则(Information Criteria)来估计模型的泛化能力,从而避免交叉验证。

核心思想

  • AIC (Akaike Information Criterion): 平衡模型拟合优度与复杂度,倾向于选择预测性能最好的模型。
  • BIC (Bayesian Information Criterion): 类似 AIC,但对复杂模型的惩罚更强,倾向于选择更简单的模型。
公式简化理解:
  • AIC ≈ -2 * log-likelihood + 2 * 参数数量
  • BIC ≈ -2 * log-likelihood + log(n) * 参数数量

适用模型

模型 说明
LassoLarsIC 使用 AIC 或 BIC 在 LARS 路径上选择最佳模型

✅ 使用示例:LassoLarsIC

python
深色版本
from sklearn.linear_model import LassoLarsIC
import numpy as np

# 使用与上面相同的数据
lasso_lars_aic = LassoLarsIC(criterion='aic', normalize=False)
lasso_lars_aic.fit(X_train, y_train)

lasso_lars_bic = LassoLarsIC(criterion='bic', normalize=False)
lasso_lars_bic.fit(X_train, y_train)

print("AIC 最佳 alpha:", lasso_lars_aic.alpha_)
print("BIC 最佳 alpha:", lasso_lars_bic.alpha_)

# 比较两者在测试集上的表现
print("AIC 模型测试得分:", lasso_lars_aic.score(X_test, y_test))
print("BIC 模型测试得分:", lasso_lars_bic.score(X_test, y_test))

优势与局限

优势 局限
🚀 极快:只需一次拟合 🔒 仅适用于特定模型(如线性模型)
📊 理论基础强 ⚠️ 假设数据分布(如高斯噪声)
💡 自动惩罚复杂度 ❌ 不适用于非参数模型

3. 袋外估计(Out-of-Bag Estimation)

Bagging 集成方法(如随机森林)中,每个基学习器使用**自助采样(bootstrap)**从原始训练集中有放回地抽取样本。

这意味着:

  • 每个基学习器大约有 37% 的样本未被选中,这些样本称为袋外(Out-of-Bag, OOB)样本
  • 可以用这些 OOB 样本来评估该学习器的性能。

袋外误差(OOB Error)

  • 对每个样本,收集所有未使用该样本进行训练的基学习器的预测。
  • 计算这些预测的平均性能(分类准确率或回归误差)。
  • 这个性能估计被称为 OOB 误差,它是对泛化误差的无偏估计。

优势

  • 免费的验证:无需划分验证集,节省数据。
  • 高效:在训练过程中自动完成,无需额外计算。
  • 可用于模型选择:通过比较不同超参数下的 OOB 误差,选择最佳配置。

支持的模型

模型 参数
RandomForestClassifier oob_score=True
RandomForestRegressor oob_score=True
ExtraTreesClassifier oob_score=True
GradientBoostingClassifier ❌ 不支持(但可通过 validation_fraction 实现类似功能)

使用示例

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

# 生成不平衡分类数据
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10,
                          n_classes=2, weights=[0.9, 0.1], random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义不同超参数下的 OOB 误差
param_candidates = [50, 100, 200]
oob_scores = []

for n in param_candidates:
    rf = RandomForestClassifier(
        n_estimators=n,
        oob_score=True,      # 启用 OOB 评估
        random_state=42,
        n_jobs=-1
    )
    rf.fit(X_train, y_train)
    oob_scores.append(rf.oob_score_)
    print(f"n_estimators={n}, OOB Score={rf.oob_score_:.4f}")

# 选择 OOB 分数最高的模型
best_n = param_candidates[np.argmax(oob_scores)]
print(f"最佳 n_estimators: {best_n}")

# 使用最佳参数训练最终模型
best_rf = RandomForestClassifier(n_estimators=best_n, random_state=42)
best_rf.fit(X_train, y_train)
print("测试集得分:", best_rf.score(X_test, y_test))

三种方法对比总结

方法 适用模型 速度 是否需要验证集 典型用途
模型特定 CV 线性模型(Ridge, Lasso, Logistic等) ⚡⚡⚡ 极快 ❌ 否(内置) 正则化参数调优
信息准则(AIC/BIC) LassoLarsIC 等 ⚡⚡⚡ 极快 ❌ 否 快速特征选择/模型选择
袋外估计(OOB) Bagging 集成(随机森林等) ⚡⚡ 快 ❌ 否 集成模型超参数调优

总结:何时使用哪种方法?

  • 如果你在训练线性模型(尤其是带正则化的)

    • 优先使用 RidgeCVLassoCVLogisticRegressionCV
    • 需要极快速度时,尝试 LassoLarsIC(AIC/BIC)。
  • 如果你在训练随机森林或 Extra-Trees

    • 启用 oob_score=True,利用 OOB 误差进行超参数选择(如 n_estimators, max_depth)。
  • 其他模型或复杂参数空间

    • 回归到 GridSearchCVRandomizedSearchCV,但可结合上述技巧优化流程。

通过合理选择这些高效方法,你可以在大幅减少计算时间的同时,获得与暴力搜索相当甚至更优的模型性能。


网站公告

今日签到

点亮在社区的每一天
去签到