You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OptunaSearchCV能否对完整机器学习Pipeline进行超参数调优?

问题与解答

问题描述

我用GridSearchCV对包含预处理、不平衡处理、特征选择及CatBoostClassifier模型的完整ImbPipeline进行超参数调优,但过程耗时极长。想改用OptunaSearchCV提速,但不确定OptunaSearchCV是否只能调优模型本身的超参数,不知道该用何种Distribution设置SelectKBest(f_classif, k=40)、RobustScaler()这类组件的参数。原代码如下:

preprocessor = ColumnTransformer(
            [
                ('OneHotEncoder', OneHotEncoder(drop='if_binary', sparse_output=False), binary_cols),
                ('CatBoostEncoder', CatBoostEncoder(random_state=RANDOM_STATE), non_binary_cat_cols),
                ('StandardScaler', StandardScaler(), num_cols)
            ],
            verbose_feature_names_out=False,
            remainder='drop'
        )
    
pipe_final = ImbPipeline([
    ('preprocessor', preprocessor),
    ('target_imbalance', ADASYN()),
    ('selection', PCA()),
    ('models', CatBoostClassifier(random_state=RANDOM_STATE))
])

# 用于CatBoostClassifier的超参数
param_grid = {
    'models__iterations': [1000, 2000, 3000],
    'models__class_weights': ['Balanced', None],
    'target_imbalance': [ADASYN(random_state=RANDOM_STATE), SMOTETomek(random_state=RANDOM_STATE),
                         SMOTE(random_state=RANDOM_STATE, k_neighbors=10), 'passthrough'],
    'preprocessor__StandardScaler': [StandardScaler(), RobustScaler(), MinMaxScaler(),
                                     PowerTransformer(), QuantileTransformer(),
                                     Normalizer(),PolynomialFeatures(degree=2, include_bias=False), 'passthrough'],
    'selection': [PCA(random_state=RANDOM_STATE, n_components="mle", svd_solver="full"),
                  SelectKBest(mutual_info_classif, k=40),
                  SelectKBest(f_classif, k=40),
                  SelectKBest(chi2, k=40),
                  SelectPercentile(mutual_info_classif, percentile=10),
                  SelectPercentile(f_classif, percentile=10),
                  SelectFromModel(CatBoostClassifier(random_state=RANDOM_STATE)),
                  SelectFromModel(LogisticRegression(random_state=RANDOM_STATE)),
                  SelectFromModel(RandomForestClassifier(random_state=RANDOM_STATE)),
                  'passthrough'],
}

gs = GridSearchCV(
    pipe_final, 
    param_grid, 
    cv=5, 
    scoring='roc_auc', 
    n_jobs=-1
)

# 启动超参数搜索
gs.fit(X, y_enc)

解答

你的理解有误,OptunaSearchCV完全支持对整个Pipeline的所有组件进行超参数调优,包括预处理、不平衡处理、特征选择环节,并非只能调优模型本身。以下是具体实现思路和代码示例:

核心思路

  1. 枚举组件类型:对于需要选择不同组件(比如不同的Scaler、采样器、特征选择器)的场景,使用Optuna的CategoricalDistribution定义候选选项,逻辑和GridSearchCV的列表枚举一致,但Optuna会智能筛选而非穷举。
  2. 调优组件参数:对于组件的可调参数(比如SelectKBest的k值、SelectPercentile的percentile值),用对应的数值分布(如IntDistribution)让Optuna在合理范围内搜索最优值,比固定值更灵活。
  3. 贝叶斯优化提速:Optuna采用贝叶斯优化算法,会根据之前试验的结果动态调整后续搜索方向,避免网格搜索的全量穷举,大幅减少无效试验,从而缩短调优时间。

修改后的代码示例

from optuna.integration import OptunaSearchCV
from optuna.distributions import CategoricalDistribution, IntDistribution

# 保留原Pipeline定义
preprocessor = ColumnTransformer(
            [
                ('OneHotEncoder', OneHotEncoder(drop='if_binary', sparse_output=False), binary_cols),
                ('CatBoostEncoder', CatBoostEncoder(random_state=RANDOM_STATE), non_binary_cat_cols),
                ('StandardScaler', StandardScaler(), num_cols)
            ],
            verbose_feature_names_out=False,
            remainder='drop'
        )
    
pipe_final = ImbPipeline([
    ('preprocessor', preprocessor),
    ('target_imbalance', ADASYN()),
    ('selection', PCA()),
    ('models', CatBoostClassifier(random_state=RANDOM_STATE))
])

# 定义Optuna搜索空间
param_distributions = {
    # 模型参数调优
    'models__iterations': IntDistribution(low=1000, high=3000, step=1000),
    'models__class_weights': CategoricalDistribution(['Balanced', None]),
    
    # 不平衡处理组件选择
    'target_imbalance': CategoricalDistribution([
        ADASYN(random_state=RANDOM_STATE), 
        SMOTETomek(random_state=RANDOM_STATE),
        SMOTE(random_state=RANDOM_STATE, k_neighbors=10), 
        'passthrough'
    ]),
    
    # 预处理Scaler选择
    'preprocessor__StandardScaler': CategoricalDistribution([
        StandardScaler(), 
        RobustScaler(), 
        MinMaxScaler(),
        PowerTransformer(), 
        QuantileTransformer(),
        Normalizer(),
        PolynomialFeatures(degree=2, include_bias=False), 
        'passthrough'
    ]),
    
    # 特征选择组件及参数调优(扩展参数灵活性)
    'selection': CategoricalDistribution([
        PCA(random_state=RANDOM_STATE, n_components="mle", svd_solver="full"),
        # 让SelectKBest的k值成为可调参数(示例:20-80之间选)
        lambda trial: SelectKBest(mutual_info_classif, k=trial.suggest_int('selection__k', 20, 80)),
        lambda trial: SelectKBest(f_classif, k=trial.suggest_int('selection__k', 20, 80)),
        lambda trial: SelectKBest(chi2, k=trial.suggest_int('selection__k', 20, 80)),
        lambda trial: SelectPercentile(mutual_info_classif, percentile=trial.suggest_int('selection__percentile', 5, 20)),
        lambda trial: SelectPercentile(f_classif, percentile=trial.suggest_int('selection__percentile', 5, 20)),
        SelectFromModel(CatBoostClassifier(random_state=RANDOM_STATE)),
        SelectFromModel(LogisticRegression(random_state=RANDOM_STATE)),
        SelectFromModel(RandomForestClassifier(random_state=RANDOM_STATE)),
        'passthrough'
    ]),
}

# 初始化OptunaSearchCV
oscv = OptunaSearchCV(
    pipe_final,
    param_distributions,
    cv=5,
    scoring='roc_auc',
    n_jobs=-1,
    n_trials=100,  # 设定总试验次数,远小于网格搜索的组合数
    random_state=RANDOM_STATE,
    verbose=1
)

# 启动超参数搜索
oscv.fit(X, y_enc)

# 查看最优参数和得分
print("最优参数:", oscv.best_params_)
print("最优ROC-AUC得分:", oscv.best_score_)

关键说明

  • 对于需要动态调整参数的组件(如SelectKBest的k),可以用lambda函数结合trial.suggest_*方法实现,让Optuna在指定范围内搜索最优值。
  • n_trials参数控制总试验次数,可根据时间预算调整,通常100-200次试验就能找到接近最优的结果,远少于网格搜索的全量组合(你的原网格组合数是324810=1920次,Optuna只需1/20的试验次数就能达到相近效果)。
  • 所有Pipeline组件的参数都可以通过组件名__参数名的方式定义搜索空间,和GridSearchCV的参数命名规则完全一致。

内容的提问来源于stack exchange,提问作者Павел Катровцев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:56:06