我刚开始在 python 中使用 statsmodel(以及许多更通用的统计数据),但我对 sm.GLM 和 smf.glm 如何计算结果之间的差异有疑问。根据我的理解,只要确保为 sm.GLM 添加系数,它们应该会产生相同的结果。然而,我在计算时发现,产生的系数是另一个系数的负结果。
例如,使用《Python 统计学习简介》一书中的示例数据集:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as smf
import statsmodels.api as sm
np.random.seed(0)
Default = pd.read_csv('../data/Default.csv')
X = Default[["balance", "income"]]
Y_=Default.default=='Yes'
X=sm.add_constant(X)
glmtest=sm.GLM(Y_,X,family=sm.families.Binomial()).fit()
glmtest.summary()
产生 0.0056 的平衡系数。但是,如果我使用 smf
mod1 = smf.glm(
formula="default~income+balance", data=Default, family=sm.families.Binomial()
).fit()
mod1.summary()
我得到的系数是 -0.0056。其他系数也同样发生了反转。由于忽略标志,结果是相同的,我认为幕后发生了一些事情,并想了解原因。
出现差异是因为
sm.GLM
直接使用布尔响应变量(True
为 1,False
为 0),但 smf.glm
自动根据类别变量的级别对其进行编码。这可以反转参考类别。为了确保获得相同的结果,请在两种方法中显式检查并对齐响应变量的编码。
import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
np.random.seed(0)
data = {
"default": np.random.choice(["Yes", "No"], size=100, p=[0.3, 0.7]),
"balance": np.random.uniform(0, 2000, size=100),
"income": np.random.uniform(20000, 100000, size=100)
}
Default = pd.DataFrame(data)
Y_ = Default.default == "Yes"
X = Default[["balance", "income"]]
X = sm.add_constant(X)
glmtest = sm.GLM(Y_, X, family=sm.families.Binomial()).fit()
mod1 = smf.glm(formula="default ~ income + balance", data=Default, family=sm.families.Binomial()).fit()
print("sm.GLM coefficients:")
print(glmtest.params)
print("\nsmf.glm coefficients:")
print(mod1.params)
这给出了
sm.GLM coefficients:
const -0.679362
balance -0.000119
income 0.000002
dtype: float64
smf.glm coefficients:
Intercept 0.679362
income -0.000002
balance 0.000119
dtype: float64