Regressão logística: Scikit Learn vs Statsmodels

31

Estou tentando entender por que a saída da regressão logística dessas duas bibliotecas fornece resultados diferentes.

Eu estou usando o conjunto de dados do UCLA Idre tutorial , a previsão admitcom base em gre, gpae rank. ranké tratado como variável categórica, por isso é primeiro convertido em variável dummy com rank_1drop. Uma coluna de interceptação também é adicionada.

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

A saída de statsmodelsé a mesma mostrada no site idre, mas não sei por que o scikit-learn produz um conjunto diferente de coeficientes. Isso minimiza alguma função de perda diferente? Existe alguma documentação que indique a implementação?

hurrikale
fonte

Respostas:

28

Sua dica para descobrir isso deve ser que as estimativas de parâmetros da estimativa de aprendizado do scikit são uniformemente menores em magnitude do que as contrapartes dos modelos de estatísticas. Isso pode levar você a acreditar que o scikit-learn aplica algum tipo de regularização de parâmetro. Você pode confirmar isso lendo a documentação do scikit-learn .

Não há como desativar a regularização no scikit-learn, mas você pode torná-lo ineficaz configurando o parâmetro de ajuste Cpara um número grande. Aqui está como isso funciona no seu caso:

# 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
tchakravarty
fonte
Muito obrigado pela explicação! Com esse resultado regularizado, eu estava tentando duplicar o resultado usando o glmnetpacote em R, mas não consegui o mesmo coeficiente. glmnet tem uma função de custo ligeiramente diferente em comparação com sklearn , mas mesmo se eu definir alpha=0em glmnet(que significa usar apenas l2-penalidade) e set 1/(N*lambda)=C, eu ainda não obter o mesmo resultado?
hurrikale
Minha intuição é que, se eu dividir os dois termos da função de custo glmnetpor lambdae definir a nova constante na fonte da probabilidade de log, que é 1/(N*lambda)igual à de sklearn, as duas funções de custo se tornarão idênticas ou estou perdendo alguma coisa?
hurrikale
@hurrikale Faça uma nova pergunta e vincule-a aqui, e eu darei uma olhada.
Tchakravarty
Obrigado! Eu postei a pergunta aqui .
hurrikale
Eu acho que a melhor maneira de desativar a regularização no scikit-learn é configurando penalty='none'.
Nzbuu 17/07
3

Outra diferença é que você configurou fit_intercept = False, que efetivamente é um modelo diferente. Você pode ver que o Statsmodel inclui a interceptação. Não ter uma interceptação certamente altera os pesos esperados nos recursos. Tente o seguinte e veja como ele se compara:

model = LogisticRegression(C=1e9)

brian dalessandro
fonte