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

scikit-learn中融合分组模型与全局模型的集成学习实现方案

示例数据集
group        feature_1        feature_2       year            dependent_variable
group_a         12               19           2010               0.4
group_a         11               13           2011               0.9
group_a         10               5            2012               1.2
group_a         16               9            2013               3.2
group_b         8               29            2010               0.6
group_b         9               33            2011               0.1 
group_b         111             15            2012               2.1 
group_b         16              19            2013               12.2  
问题背景

使用特征feature_1、feature_2预测因变量dependent_variable,构建两类基础模型:

  • 分组独立模型:每个分组单独训练独立子模型
  • 全局模型:使用全量可用数据训练统一模型
    两类模型均以2010-2012年数据为训练集、2013年数据为测试集,需要构建兼容所有符合scikit-learn规范模型的集成方案,适配包含更多分组、年份、特征的真实数据集。
可落地方案

整个方案完全遵循scikit-learn的Estimator接口规范,不需要修改基模型的底层逻辑,线性模型、树模型、集成模型等所有符合sklearn API的模型都可以直接接入。

1. 基础模型标准化封装

首先把分组独立模型封装成符合sklearn规范的估计器,全局模型可以直接用原生sklearn模型不需要额外处理。封装参考代码:

from sklearn.base import BaseEstimator, RegressorMixin, clone
import pandas as pd
import numpy as np

class GroupWiseRegressor(BaseEstimator, RegressorMixin):
    def __init__(self, base_model, group_col="group", fallback_model=None):
        self.base_model = base_model
        self.group_col = group_col
        self.fallback_model = fallback_model
        self.group_models_ = {}

    def fit(self, X, y):
        X = X.reset_index(drop=True)
        y = y.reset_index(drop=True)
        # 训练各分组子模型
        for group_name, sub_idx in X.groupby(self.group_col).groups.items():
            sub_X = X.loc[sub_idx].drop(columns=[self.group_col])
            sub_y = y.loc[sub_idx]
            self.group_models_[group_name] = clone(self.base_model).fit(sub_X, sub_y)
        # 训练兜底模型(传入全局模型即可处理未见过的新分组)
        if self.fallback_model is not None:
            self.fallback_model_ = clone(self.fallback_model).fit(
                X.drop(columns=[self.group_col]), y
            )
        return self

    def predict(self, X):
        X = X.reset_index(drop=True)
        preds = np.zeros(len(X))
        for group_name, sub_idx in X.groupby(self.group_col).groups.items():
            sub_X = X.loc[sub_idx].drop(columns=[self.group_col])
            if group_name in self.group_models_:
                preds[sub_idx] = self.group_models_[group_name].predict(sub_X)
            else:
                # 新分组用兜底模型输出
                preds[sub_idx] = self.fallback_model_.predict(sub_X)
        return preds

如果是分类任务,把继承的RegressorMixin换成ClassifierMixin,对应实现predict_proba接口即可。

2. 三种集成策略(全兼容sklearn生态)

策略1:加权平均(实现成本最低,鲁棒性最强)

不需要额外训练元模型,从2010-2012年的训练集里按时间切分出验证集(比如用2012年数据做验证,绝对不能碰2013年测试集),网格搜索权重系数w(取值范围0~1),使得验证集上w * 分组模型预测值 + (1-w) * 全局模型预测值的误差最小即可。如果不同分组数据分布差异大,可以给每个分组单独搜索最优权重,进一步提升效果。

策略2:Stacking堆叠(效果上限更高)

直接用sklearn原生的StackingRegressor/StackingClassifier实现:第一层基学习器放封装好的分组独立模型、全局模型,第二层元学习器选简单的线性模型(比如线性回归、岭回归,不要选太复杂的模型防止过拟合)。注意生成第一层交叉验证预测值时,要严格按时间+分组维度切分,避免同一年同组的数据同时出现在训练和验证折里造成数据泄露。

策略3:动态路由(适配分组异质性极强的场景)

从训练集里生成两个基础模型在验证集上的预测误差标签:对于每个样本,如果分组模型预测误差更小标记为0,全局模型预测误差更小标记为1。用这个标签训练一个轻量的sklearn分类模型(比如浅决策树、逻辑回归)作为路由模型,预测时先由路由模型判断当前样本应该采信哪个基础模型的输出,直接返回对应模型的预测值即可。

3. 工作流统一封装

把最终选择的集成逻辑封装成独立的sklearn估计器,实现fit、predict、get_params、set_params标准接口,后续可以直接接入Pipeline、GridSearchCV、cross_validate等sklearn原生工具,不管后续新增多少分组、特征,或者更换什么基模型,都不需要修改核心代码。

注意事项:所有调参、权重搜索、元模型训练环节,只能使用2010-2012年的训练集数据,严格按时间维度切分验证集,绝对不能泄露2013年测试集的任何信息,否则离线评估指标会严重虚高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:24:27