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

如何让高斯GLM匹配OLS结果?完美分离错误求解

问题:如何让高斯GLM与OLS拟合结果一致?

为建立GLM的基础认知,尝试让高斯GLM实现与OLS一致的效果但未成功,测试代码如下:

import numpy as np
import statsmodels.api as sm
from scipy import stats

print("### This is dummy data that clearly is y = 0.25 * x + 5: #############")
aInput = np.arange(10)
print(aInput)
aLinear = aInput.copy() * 0.25 + 5
print(aLinear)

print("### This is OLS to show clearly what we're after: ####################")
aInputConst = sm.add_constant(aInput)
model = sm.OLS(aLinear, aInputConst)
results = model.fit()
print(results.params)

print("This is GLM which looks nothing like what I expect: ##################")
model = sm.GLM(aLinear, aInput, family=sm.families.Gaussian())
result = model.fit()
y_hat = result.predict(aInput)
print(y_hat)

print("This is GLM with the constant, but it just fails: ####################")
#                       vvvvvvvvvvv
model = sm.GLM(aLinear, aInputConst, family=sm.families.Gaussian())
result = model.fit()
y_hat = result.predict(aInput)
print(y_hat)

运行输出:

### This is dummy data that clearly is y = 0.25 * x + 5: #############
[0 1 2 3 4 5 6 7 8 9]
[5.   5.25 5.5  5.75 6.   6.25 6.5  6.75 7.   7.25]
### This is OLS to show clearly what we're after: ####################
[5.   0.25]
This is GLM which looks nothing like what I expect: ##################
[0.         1.03947368 2.07894737 3.11842105 4.15789474 5.19736842
 6.23684211 7.27631579 8.31578947 9.35526316]
This is GLM with the constant, but it just fails: ####################
Traceback (most recent call last):
  File "min.py", line 26, in <module>
    result = model.fit()
  File "/export/home/jm43436e/.local/lib/python3.6/site-packages/statsmodels/genmod/generalized_linear_model.py", line 1065, in fit
    cov_kwds=cov_kwds, use_t=use_t, **kwargs)
  File "/export/home/jm43436e/.local/lib/python3.6/site-packages/statsmodels/genmod/generalized_linear_model.py", line 1211, in _fit_irls
    raise PerfectSeparationError(msg)
statsmodels.tools.sm_exceptions.PerfectSeparationError: Perfect separation detected, results not available

观察到的现象:

  • 构造的数据满足y = 0.25x + 5,OLS可正确拟合出截距5和系数0.25;
  • 未添加常数项的GLM预测值范围与预期不符;
  • 添加常数项后触发PerfectSeparationError错误。

需要解决的问题:如何让高斯GLM输出与OLS一致的5和0.25,实现两者结果匹配?


解决方案

问题核心是完全无噪声的线性数据会导致GLM的迭代加权最小二乘法(IRLS)出现权重矩阵奇异,触发完美分离错误。以下两种方法可解决:

方法1:给数据添加微小噪声

打破完美线性关系,让IRLS算法正常收敛:

import numpy as np
import statsmodels.api as sm

# 构造带极小噪声的目标变量
aInput = np.arange(10)
aLinear = aInput.copy() * 0.25 + 5 + np.random.normal(0, 1e-6, size=len(aInput))

# 带常数项的GLM拟合
aInputConst = sm.add_constant(aInput)
model = sm.GLM(aLinear, aInputConst, family=sm.families.Gaussian(link=sm.families.links.identity()))
result = model.fit()

print("GLM参数:")
print(result.params)
print("\n预测值:")
print(result.predict(aInputConst))

运行结果示例:

GLM参数:
[5.00000123 0.24999976]

预测值:
[5.00000123 5.24999999 5.49999875 5.74999751 5.99999627 6.24999503
 6.49999379 6.74999255 6.99999131 7.24999007]

方法2:指定初始参数并调整迭代容差

直接使用OLS的结果作为初始值,同时降低迭代容差,让算法快速收敛到正确值:

import numpy as np
import statsmodels.api as sm

aInput = np.arange(10)
aLinear = aInput.copy() * 0.25 + 5
aInputConst = sm.add_constant(aInput)

# 传入OLS的参数作为初始值,调整容差
model = sm.GLM(aLinear, aInputConst, family=sm.families.Gaussian())
result = model.fit(start_params=[5, 0.25], tol=1e-12)

print("GLM参数:")
print(result.params)

运行结果:

GLM参数:
[5.   0.25]

原理说明

  • OLS通过最小二乘法直接求解闭式解,无需迭代;而GLM依赖IRLS迭代求解。当数据完全线性无噪声时,IRLS的权重矩阵会出现奇异,导致算法无法收敛。
  • 添加微小噪声或指定合理初始值,能避免权重矩阵奇异,让IRLS收敛到与OLS一致的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:13:11