逻辑回归:Scikit学习与统计模型


31

我试图理解为什么这两个库的逻辑回归的输出会给出不同的结果。

我使用从加州大学洛杉矶分校idre数据集教程,预测admit基础上gregparankrank被视为分类变量,因此先将其rank_1删除后转换为虚拟变量。还添加了一个拦截列。

df = pd.read_csv("https://stats.idre.ucla.edu/stat/data/binary.csv")
y, X = dmatrices('admit ~ gre + gpa + C(rank)', df, return_type = 'dataframe')
X.head()
>  Intercept  C(rank)[T.2]  C(rank)[T.3]  C(rank)[T.4]  gre   gpa
0          1             0             1             0  380  3.61
1          1             0             1             0  660  3.67
2          1             0             0             0  800  4.00
3          1             0             0             1  640  3.19
4          1             0             0             1  520  2.93

# Output from scikit-learn
model = LogisticRegression(fit_intercept = False)
mdl = model.fit(X, y)
model.coef_
> array([[-1.35417783, -0.71628751, -1.26038726, -1.49762706,  0.00169198,
     0.13992661]]) 
# corresponding to predictors [Intercept, rank_2, rank_3, rank_4, gre, gpa]

# Output from statsmodels
logit = sm.Logit(y, X)
logit.fit().params
> Optimization terminated successfully.
     Current function value: 0.573147
     Iterations 6
Intercept      -3.989979
C(rank)[T.2]   -0.675443
C(rank)[T.3]   -1.340204
C(rank)[T.4]   -1.551464
gre             0.002264
gpa             0.804038
dtype: float64

的输出statsmodels与idre网站上显示的输出相同,但是我不确定scikit-learn为什么会产生不同的系数集。它会最小化某些损失函数吗?是否有任何文件说明执行情况?

Answers:


28

您可以弄清楚这一点的线索应该是,来自scikit-learn估计的参数估计在大小上始终小于statsmodels对应参数。这可能使您相信scikit-learn应用了某种参数正则化。您可以阅读scikit-learn文档来确认。

无法在scikit-learn中关闭正则化,但是可以通过将Tuning参数C设置为较大数值来使其无效。这是您的情况下的工作方式:

# module imports
from patsy import dmatrices
import pandas as pd
from sklearn.linear_model import LogisticRegression
import statsmodels.discrete.discrete_model as sm

# read in the data & create matrices
df = pd.read_csv("http://www.ats.ucla.edu/stat/data/binary.csv")
y, X = dmatrices('admit ~ gre + gpa + C(rank)', df, return_type = 'dataframe')

# sklearn output
model = LogisticRegression(fit_intercept = False, C = 1e9)
mdl = model.fit(X, y)
model.coef_

# sm
logit = sm.Logit(y, X)
logit.fit().params

非常感谢您的解释!有了这个正规化的结果,我正尝试使用glmnet R中包,但是无法获得相同的系数。与sklearn相比,glmnet的成本函数略有不同,但是即使我设置alpha=0glmnet(意味着仅使用l2-penalty)并设置了set 1/(N*lambda)=C,我仍然不会得到相同的结果?
hurrikale '16

我的直觉是,如果我把成本函数的两个术语中glmnetlambda,并设置在数似然的字体恒新,这是1/(N*lambda)等于在sklearn,这两个成本函数变得相同,还是我失去了一些东西?
hurrikale '16

@hurrikale提出一个新问题,并将其链接到这里,我会看一看。
tchakravarty

谢谢!我在这里发布了问题。
hurrikale '16

我认为在scikit-learn中关闭正则化的最好方法是通过设置penalty='none'
纽布尔

3

另一个区别是您设置了fit_intercept = False,这实际上是一个不同的模型。您可以看到Statsmodel包括拦截。没有截距肯定会更改要素的预期权重。请尝试以下操作,并比较一下:

model = LogisticRegression(C=1e9)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.