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

如何在Python中对sm.GLM广义线性回归模型执行交叉验证

报错根源

你传给cross_val_score的glm_model是调用fit()后返回的GLMResultsWrapper训练结果对象,不是可重复训练的模型实例,且statsmodels原生模型不符合sklearn的estimator接口规范,因此触发类型错误。
另外你现有代码还存在两个可修复问题:

  • 拆分数据集时调用的X、Y未提前赋值,你之前定义的特征和标签变量为exog、endog
  • 评估指标参数写法错误,负均方误差的正确参数值为neg_mean_squared_error,中间为下划线而非空格
解决方案1:手动实现K折交叉验证(最灵活,无额外适配成本)

直接通过KFold拆分循环训练验证,代码示例如下:

import pandas as pd
import statsmodels.api as sm
import numpy as np
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import mean_squared_error

Test = pd.read_csv(r'D:\myfile.csv')
y = Test['Y']
X = Test[['log_X1', 'log_A', 'log_B']]

# 拆分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=1)

# 10折交叉验证
crossvalidation = KFold(n_splits=10, shuffle=True, random_state=1)
scores = []

for train_idx, val_idx in crossvalidation.split(X_train):
    # 取当前折的训练/验证数据
    X_tr, X_val = X_train.iloc[train_idx], X_train.iloc[val_idx]
    y_tr, y_val = y_train.iloc[train_idx], y_train.iloc[val_idx]
    # 初始化并训练模型,family可根据需求替换为Gamma等分布
    glm = sm.GLM(y_tr, X_tr, family=sm.families.Gaussian(link=sm.families.links.log()))
    glm_res = glm.fit()
    # 验证集预测并计算负均方误差,和sklearn的scoring逻辑对齐
    y_pred = glm_res.predict(X_val)
    neg_mse = -mean_squared_error(y_val, y_pred)
    scores.append(neg_mse)

# 输出交叉验证结果
print(f"各折负均方误差: {scores}")
print(f"平均负均方误差: {np.mean(scores)}")
解决方案2:封装为sklearn兼容接口(可直接调用cross_val_score)

如果希望复用sklearn的交叉验证、网格搜索等工具,可以将sm.GLM封装为符合sklearn estimator规范的类:

import pandas as pd
import statsmodels.api as sm
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.model_selection import train_test_split, cross_val_score, KFold

# 自定义封装类
class SMGLMRegressor(BaseEstimator, RegressorMixin):
    def __init__(self, family):
        self.family = family
        self._model = None
        self._fit_res = None
    
    def fit(self, X, y):
        self._model = sm.GLM(y, X, family=self.family)
        self._fit_res = self._model.fit()
        return self
    
    def predict(self, X):
        return self._fit_res.predict(X)

# 数据读取与拆分
Test = pd.read_csv(r'D:\myfile.csv')
y = Test['Y']
X = Test[['log_X1', 'log_A', 'log_B']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=1)

# 初始化包装后的模型,family可替换为Gamma等
glm_est = SMGLMRegressor(family=sm.families.Gaussian(link=sm.families.links.log()))
crossvalidation = KFold(n_splits=10, shuffle=True, random_state=1)

# 直接调用cross_val_score
scores = cross_val_score(glm_est, X_train, y_train, scoring="neg_mean_squared_error", cv=crossvalidation)
print(f"交叉验证得分: {scores}")
print(f"平均得分: {scores.mean()}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:45:01