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

Scikit-learn Pipeline类GLMM方案:交互项添加与GLMM集成问询

心脏病数据集下类GLMM实现与Pipeline交互特征构建方案

问题1:在Pipeline中添加分组变量与数值变量的交互特征

要生成hospital_2_age这类交互项,可通过自定义Transformer配合ColumnTransformer实现精准的特征交互,步骤如下:

实现思路

  1. 拆分特征类型:将数值特征(age、chol等)与分组特征(hospital)分开预处理;
  2. 预处理阶段:数值特征做标准化,分组特征做独热编码;
  3. 自定义交互生成器:提取独热后的分组特征与预处理后的数值特征,生成两两乘积的交互项,再合并到原特征集。

代码示例

import numpy as np
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.linear_model import LogisticRegression

# 自定义交互特征生成器
class InteractionFeatureGenerator(BaseEstimator, TransformerMixin):
    def __init__(self, group_col_start_idx):
        self.group_col_start_idx = group_col_start_idx  # 独热分组列的起始索引

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        # 拆分分组特征(独热后)与数值特征
        group_features = X[:, self.group_col_start_idx:]
        numeric_features = X[:, :self.group_col_start_idx]
        
        # 生成所有分组-数值的交互项
        interactions = []
        for group_idx in range(group_features.shape[1]):
            for num_idx in range(numeric_features.shape[1]):
                interactions.append(group_features[:, group_idx] * numeric_features[:, num_idx])
        
        # 合并原特征与交互项
        return np.hstack([X, np.array(interactions).T])

# 定义特征列
numeric_cols = ['age', 'chol', 'trestbps', 'thalach']
group_col = ['hospital']

# 构建预处理管道
preprocessor = ColumnTransformer(
    transformers=[
        ("num_scaler", StandardScaler(), numeric_cols),
        ("cat_onehot", OneHotEncoder(sparse_output=False, drop="first"), group_col)
    ]
)

# 完整Pipeline:预处理 → 生成交互项 → 逻辑回归
full_pipeline = Pipeline([
    ("preprocess", preprocessor),
    ("add_interactions", InteractionFeatureGenerator(group_col_start_idx=len(numeric_cols))),
    ("log_reg", LogisticRegression(max_iter=1000))
])

# 拟合模型(假设df为预处理后的心脏病数据集)
# full_pipeline.fit(df[numeric_cols + group_col], df["target"])

问题2:无需手动交互项的类GLMM平滑实现

由于Scikit-learn原生不支持GLMM,可通过包装Statsmodels混合模型为Sklearn兼容Estimator的方式,融入现有Pipeline工作流,自动处理分组随机效应,无需手动生成交互项。

实现思路

  1. 用ColumnTransformer预处理数值特征(分组特征保留原类别,Statsmodels公式可自动处理);
  2. 自定义Estimator包装Statsmodels的MixedLM(支持广义线性混合模型,指定Binomial家族实现逻辑斯蒂混合模型);
  3. 通过公式语法直接定义固定效应与随机效应,比如(1 | hospital)表示医院级别的随机截距,(age | hospital)表示随机斜率。

代码示例

import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.regression.mixed_linear_model import MixedLM
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler
from sklearn.base import BaseEstimator, ClassifierMixin

# 自定义GLMM包装器,兼容Sklearn接口
class GLMMClassifier(BaseEstimator, ClassifierMixin):
    def __init__(self, formula, group_col):
        self.formula = formula
        self.group_col = group_col
        self.model = None
        self.results = None

    def fit(self, X, y):
        # 合并特征与目标变量,适配Statsmodels公式
        df = X.copy()
        df["target"] = y
        # 构建逻辑斯蒂混合模型(Binomial家族对应logit链接)
        self.model = MixedLM.from_formula(
            formula=self.formula,
            data=df,
            groups=df[self.group_col],
            family=sm.families.Binomial()
        )
        self.results = self.model.fit()
        return self

    def predict(self, X):
        # 预测类别(0/1)
        probs = self.results.predict(X)
        return (probs >= 0.5).astype(int)

    def predict_proba(self, X):
        # 返回两类概率
        probs = self.results.predict(X)
        return np.vstack([1 - probs, probs]).T

# 预处理管道:仅标准化数值特征,分组特征原样保留
preprocessor = ColumnTransformer(
    transformers=[
        ("num_scaler", StandardScaler(), numeric_cols),
        ("cat_passthrough", "passthrough", group_col)
    ],
    remainder="drop"
)

# 完整Pipeline:预处理 → GLMM分类器
glmm_pipeline = Pipeline([
    ("preprocess", preprocessor),
    ("glmm", GLMMClassifier(
        formula="target ~ age + chol + trestbps + thalach + (1 | hospital)",
        group_col="hospital"
    ))
])

# 拟合模型
# glmm_pipeline.fit(df[numeric_cols + group_col], df["target"])

说明

  • 公式中(1 | hospital)表示每个医院拥有独立的随机截距,若需建模随机斜率(即不同医院的age系数不同),可改为(age | hospital);
  • 该方式完全替代手动生成交互项的繁琐操作,更贴合GLMM的统计逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:15:12