Régression logistique: Scikit Learn vs Statsmodels

31

J'essaie de comprendre pourquoi la sortie de la régression logistique de ces deux bibliothèques donne des résultats différents.

J'utilise l'ensemble de données du didacticiel UCLA idre , la prévision admitbasée sur gre, gpaet rank. rankest traité comme une variable catégorielle, il est donc d'abord converti en variable fictive avec rank_1drop. Une colonne d'interception est également ajoutée.

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

Le résultat de statsmodelsest le même que celui indiqué sur le site Web idre, mais je ne sais pas pourquoi scikit-learn produit un ensemble différent de coefficients. Cela minimise-t-il une fonction de perte différente? Existe-t-il une documentation indiquant la mise en œuvre?

hurrikale
la source

Réponses:

28

Votre indice pour comprendre cela devrait être que les estimations des paramètres de l'estimation scikit-learn sont uniformément plus petites que celles des modèles statistiques. Cela pourrait vous faire croire que scikit-learn applique une sorte de régularisation des paramètres. Vous pouvez le confirmer en lisant la documentation de scikit-learn .

Il n'y a aucun moyen de désactiver la régularisation dans scikit-learn, mais vous pouvez la rendre inefficace en définissant le paramètre de réglage Csur un grand nombre. Voici comment cela fonctionne dans votre cas:

# 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
la source
Merci beaucoup pour l'éxplication! Avec ce résultat régularisé, j'essayais de dupliquer le résultat en utilisant le glmnetpackage dans R, mais je n'ai pas pu obtenir le même coefficient. glmnet a une fonction de coût légèrement différente de celle de sklearn , mais même si j'installe (c'est- alpha=0à glmnet-dire n'utilise que l2-penalty) et que 1/(N*lambda)=Cje définis , je n'obtiens toujours pas le même résultat?
hurrikale
Mon intuition est que si je divise les deux termes de la fonction de coût en glmnetpar lambdaet que je mets la nouvelle constante en police de log-vraisemblance, qui est 1/(N*lambda)égale à celle de sklearn, les deux fonctions de coût deviennent identiques, ou manque-t-il quelque chose?
hurrikale
@hurrikale Posez une nouvelle question et liez-la ici, et je vais y jeter un œil.
tchakravarty
Merci! J'ai posté la question ici .
hurrikale
Je pense que la meilleure façon de désactiver la régularisation dans scikit-learn est de définir penalty='none'.
Nzbuu
3

Une autre différence est que vous avez défini fit_intercept = False, qui est en fait un modèle différent. Vous pouvez voir que Statsmodel inclut l'interception. Ne pas avoir d'interception modifie sûrement les pondérations attendues sur les fonctionnalités. Essayez ce qui suit et voyez comment cela se compare:

model = LogisticRegression(C=1e9)

brian dalessandro
la source