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

使用statsmodels拟合MixedLM后执行ANOVA出现维度不匹配问题

MixedLM模型Type 2 ANOVA维度不匹配错误排查

问题场景

已成功使用statsmodels的MixedLM.from_formula拟合包含虚拟变量的GLIMMIX模型,但执行Type 2 ANOVA时出现维度不匹配错误。

模型代码

import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf

# 补充原代码缺失的K定义
K = 12
T_ctr_vec = np.random.rand(15,12)
T_pat_vec = np.random.rand(15,12)

mask_K = np.ones((K,K)) - np.eye(K,K)
mask_K_ind = np.where(mask_K != 0)

n_pat = T_pat_vec.shape[0]
n_ctr = T_ctr_vec.shape[0]

Y = np.concatenate((T_ctr_vec, T_pat_vec), axis=1).T.flatten()

TT = np.tile(mask_K_ind[0], n_ctr + n_pat)

G_pat = np.full(n_pat, np.nan)
G_pat[0:15] = 3
G = np.concatenate((np.ones(n_ctr), G_pat), axis=0)
G = np.repeat(G, len(mask_K_ind[0]))

S = np.tile(np.arange(1, n_ctr+n_pat+1), (1, len(mask_K_ind[0])))
S = S.flatten()

tbl_gmle_ = pd.DataFrame({'TT':TT,'S':S,'G':G}).astype('category')
tbl_gmle_t_Y = pd.DataFrame({'Y':Y})
tbl_gmle_t = tbl_gmle_.join(tbl_gmle_t_Y)

# 拟合模型
formula = 'Y ~ 1 + TT * G + C(S)'
model = sm.MixedLM.from_formula(formula, data=tbl_gmle_t, groups=tbl_gmle_t["S"])
model.family = sm.families.Gaussian()
result = model.fit()

# 执行Type 2 ANOVA时出错
anova_table = sm.stats.anova_lm(result,typ=2)

错误信息

Cell In [814], line 2
      1 # Perform ANOVA
----> 2 anova_table = sm.stats.anova_lm(result,typ=2)
      4 # Print the ANOVA table
      5 print(anova_table)

File /opt/homebrew/Caskroom/miniforge/base/envs/working°env/lib/python3.8/site-packages/statsmodels/stats/anova.py:349, in anova_lm(*args, **kwargs)
    347 if len(args) == 1:
    348     model = args[0]
---> 349     return anova_single(model, **kwargs)
    351 if typ not in [1, "I"]:
    352     raise ValueError("Multiple models only supported for type I. "
    353                      "Got type %s" % str(typ))

File /opt/homebrew/Caskroom/miniforge/base/envs/working°env/lib/python3.8/site-packages/statsmodels/stats/anova.py:80, in anova_single(model, **kwargs)
     77     return anova1_lm_single(model, endog, exog, nobs, design_info, table,
     78                             n_rows, test, pr_test, robust)
     79 elif typ in [2, "II"]:
---> 80     return anova2_lm_single(model, design_info, n_rows, test, pr_test,
     81                             robust)
     82 elif typ in [3, "III"]:
     83     return anova3_lm_single(model, design_info, n_rows, test, pr_test,
     84                             robust)

File /opt/homebrew/Caskroom/miniforge/base/envs/working°env/lib/python3.8/site-packages/statsmodels/stats/anova.py:201, in anova2_lm_single(model, design_info, n_rows, test, pr_test, robust)
    198 L2 = np.eye(model.model.exog.shape[1])[L2]
    200 if L2.size:
---> 201     LVL = np.dot(np.dot(L1,robust_cov),L2.T)
    202     from scipy import linalg
    203     orth_compl,_ = linalg.qr(LVL)

File <__array_function__ internals>:180, in dot(*args, **kwargs)

ValueError: shapes (6,37) and (38,38) not aligned: 37 (dim 1) != 38 (dim 0)

错误原因

  1. 固定效应与随机效应的冗余冲突:
    公式中的C(S)将分组变量S转为虚拟变量作为固定效应,但同时又通过groups=tbl_gmle_t["S"]指定S为随机效应分组,这会导致设计矩阵的固定效应列数与模型参数的协方差矩阵维度不匹配。原错误中的(6,37)是Type 2 ANOVA计算时的对比矩阵维度,而(38,38)是完整参数的协方差矩阵维度,两者因重复定义S的效应出现维度差异。

  2. statsmodels对混合模型ANOVA的支持局限:
    sm.stats.anova_lm最初是为普通线性模型(OLS)设计的,对混合效应模型(MixedLM)的Type 2/3 ANOVA支持不完善,其内部计算逻辑没有考虑混合模型的参数结构(固定效应+随机效应),导致矩阵运算时出现维度对齐失败。

解决方法

  • 移除固定效应中的C(S):
    由于groups=S已经为每个S分组添加了随机截距,无需再将C(S)放入固定效应公式,修改后的公式为:

    formula = 'Y ~ 1 + TT * G'
    

    这样可以消除冗余效应,确保设计矩阵与协方差矩阵维度匹配。

  • 使用混合模型专用的ANOVA方法:
    若需要对混合模型做Type 2/3 ANOVA,可选择:

    • 手动计算平方和:基于模型的固定效应设计矩阵和参数协方差矩阵,自行实现Type 2平方和的计算逻辑;
    • 切换到更适配的库:比如pymer4(Python),该工具对混合效应模型的ANOVA支持更成熟。
  • 验证维度一致性:
    修改模型后,可通过以下代码检查设计矩阵和协方差矩阵的维度是否匹配:

    print("设计矩阵维度:", model.model.exog.shape)
    print("协方差矩阵维度:", result.cov_params().shape)
    

    确保两者的列数/行数一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:24:57