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

使用RandomizedSearchCV优化LGBM多分类模型时特征不匹配报错求解

问题解决:带自定义评分的RandomizedSearchCV优化LGBM多分类模型报错处理

问题场景

要通过带自定义评分函数的RandomizedSearchCV优化多分类LGBM模型,自定义评分需要额外的scoring_info_cols数据(仅用于分数计算,不可用于模型训练)。features_train和features_val均包含训练特征+这些额外列,但调用random_search.fit()时出现以下错误:

ValueError: Length of feature_name(25) and num_feature(7) don't match

其中7是训练用特征数,25是7个训练特征加18个额外scoring_info列,推测ColumnTransformer仅处理了训练数据,未处理验证集。

错误原因

你的判断完全正确:Pipeline只会对fit()传入的主训练数据(features_train)执行前置的drop_scoring_info处理,但通过lgbm__eval_set传入的验证集是原始的features_val,包含全部25列。而LGBM训练时已经适配了7列的训练特征,验证集特征数不匹配就会触发报错。

解决方案

方案1:提前预处理验证集(简单直接)

先使用同一个ColumnTransformer处理验证集,确保训练和验证的特征数一致:

# 先让dropper拟合训练数据,保证处理逻辑一致
dropper.fit(features_train)
# 处理验证集,移除scoring_info_cols
features_val_processed = dropper.transform(features_val)

# 修改fit调用,传入处理后的验证集
random_result = random_search.fit(
    features_train, target_train, 
    lgbm__eval_set=[(features_val_processed, target_val)],
    lgbm__eval_metric=my_eval_metric
)

方案2:自定义LGBM包装器(适配交叉验证场景)

如果使用交叉验证(cv=5),每折的验证集都需要单独处理,提前预处理会比较繁琐。可以自定义一个包装类,让LGBM在训练时自动对eval_set执行前置预处理:

from sklearn.base import BaseEstimator, ClassifierMixin
import lightgbm as lgb

class LGBMWithEvalPreprocess(BaseEstimator, ClassifierMixin):
    def __init__(self, preprocessor, lgb_params=None):
        self.preprocessor = preprocessor
        self.lgb_params = lgb_params or {}
        self.model = lgb.LGBMClassifier(**self.lgb_params)
    
    def fit(self, X, y, eval_set=None, eval_metric=None, **fit_params):
        # 预处理训练数据
        X_processed = self.preprocessor.fit_transform(X)
        # 预处理验证集(如果传入)
        processed_eval_set = []
        if eval_set is not None:
            for X_val, y_val in eval_set:
                X_val_processed = self.preprocessor.transform(X_val)
                processed_eval_set.append((X_val_processed, y_val))
        # 调用LGBM原生fit方法
        self.model.fit(X_processed, y, eval_set=processed_eval_set, eval_metric=eval_metric, **fit_params)
        return self
    
    def predict(self, X):
        X_processed = self.preprocessor.transform(X)
        return self.model.predict(X_processed)
    
    def predict_proba(self, X):
        X_processed = self.preprocessor.transform(X)
        return self.model.predict_proba(X_processed)

# 重新构建模型
dropper = ColumnTransformer(
    [("drop", "drop", scoring_info_cols)], remainder="passthrough"
)
lgbm_model = LGBMWithEvalPreprocess(
    preprocessor=dropper,
    lgb_params={"early_stopping_rounds": 20}
)

# RandomizedSearchCV配置不变,fit时直接传原始验证集
random_search = RandomizedSearchCV(
    lgbm_model,
    param_distributions=param_dist,
    cv=5,
    scoring=custom_scoring_function,
    n_iter=100,
    random_state=42,
    n_jobs=1
)
random_result = random_search.fit(
    features_train, target_train, 
    eval_set=[(features_val, target_val)],
    eval_metric=my_eval_metric
)

自定义评分函数注意事项

因为RandomizedSearchCV的自定义评分函数会接收原始的X(包含scoring_info_cols)、y_true和模型,所以你可以直接在custom_scoring_function中从X提取所需的额外列,结合模型预测结果计算分数,无需额外处理。

内容的提问来源于stack exchange,提问作者riccio777

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:57:22