Régression logistique: Scikit Learn vs glmnet


15

J'essaie de dupliquer les résultats de sklearnla bibliothèque de régression logistique en utilisant le glmnetpackage dans R.

À partir de la documentation desklearn régression logistique , il essaie de minimiser la fonction de coût sous pénalité l2 min w , c 1

minw,c12wTw+Cje=1NJournal(exp(-yje(XjeTw+c))+1)

À partir des vignettes de glmnet, sa mise en œuvre minimise une fonction de coût légèrement différente

minβ,β0-[1Nje=1Nyje(β0+XjeTβ)-Journal(1+e(β0+XjeTβ))]+λ[(α-1)||β||22/2+α||β||1]

Avec quelques ajustements dans la deuxième équation, et en fixant , λ min β , β 0 1α=0

λminβ,β01Nλje=1N[-yje(β0+XjeTβ)+Journal(1+e(β0+XjeTβ))]+||β||22/2

qui ne diffère de la sklearnfonction de coût que par un facteur si défini sur 1λ, donc je m'attendais à la même estimation de coefficient des deux packages. Mais ils sont différents. J'utilise l'ensemble de données dudidacticielUCLA idre, la prévisionbasée sur,et. Il y a 400 observations, donc avecC=1,λ=0,0025.1Nλ=CadmitgregparankC=1λ=0,0025

#python sklearn
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

model = LogisticRegression(fit_intercept = False, C = 1)
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]


> # R glmnet
> df = fread("https://stats.idre.ucla.edu/stat/data/binary.csv")
> X = as.matrix(model.matrix(admit~gre+gpa+as.factor(rank), data=df))[,2:6]
> y = df[, admit]
> mylogit <- glmnet(X, y, family = "binomial", alpha = 0)
> coef(mylogit, s = 0.0025)
6 x 1 sparse Matrix of class "dgCMatrix"
                    1
(Intercept)      -3.984226893
gre               0.002216795
gpa               0.772048342
as.factor(rank)2 -0.530731081
as.factor(rank)3 -1.164306231
as.factor(rank)4 -1.354160642

La Rsortie est en quelque sorte proche de la régression logistique sans régularisation, comme on peut le voir ici . Suis-je en train de manquer quelque chose ou de faire quelque chose de mal à l'évidence?

Mise à jour: J'ai également essayé d'utiliser le LiblineaRpackage Rpour effectuer le même processus, et pourtant j'ai obtenu un autre ensemble d'estimations différent ( liblinearest également le solveur sklearn):

> fit = LiblineaR(X, y, type = 0, cost = 1)
> print(fit)
$TypeDetail
[1] "L2-regularized logistic regression primal (L2R_LR)"
$Type
[1] 0
$W
            gre          gpa as.factor(rank)2 as.factor(rank)3 as.factor(rank)4         Bias
[1,] 0.00113215 7.321421e-06     5.354841e-07     1.353818e-06      9.59564e-07 2.395513e-06

Mise à jour 2: désactiver la normalisation dans glmnetdonne:

> mylogit <- glmnet(X, y, family = "binomial", alpha = 0, standardize = F)
> coef(mylogit, s = 0.0025)
6 x 1 sparse Matrix of class "dgCMatrix"
                     1
(Intercept)      -2.8180677693
gre               0.0034434192
gpa               0.0001882333
as.factor(rank)2  0.0001268816
as.factor(rank)3 -0.0002259491
as.factor(rank)4 -0.0002028832

Avez-vous déjà compris cela?
Huey

Réponses:


8

L2

D'autant plus que votre greterme est à une échelle plus grande que les autres variables, cela changera les coûts relatifs de l'utilisation des différentes variables pour les pondérations.

Notez également qu'en incluant un terme d'interception explicite dans les fonctionnalités, vous régularisez l'interception du modèle. Cela n'est généralement pas fait, car cela signifie que votre modèle n'est plus covariant au décalage de toutes les étiquettes par une constante.


glmnetpermet de désactiver la standardisation des entrées, mais les coefficients estimés sont encore plus différents, voir ci-dessus. De plus, j'ai explicitement inclus le terme d'interception dans sklearncar il en glmnetinclut un automatiquement, c'est pour s'assurer que les entrées des deux modèles sont les mêmes.
hurrikale

2
@hurrikale Je pense que glmnet ne régularise probablement pas l'interception, mais sklearn l'est. Supprimez la colonne d'interception de Xet passez fit_intercept=True(par défaut) à LogisticRegression. Mais il se passe probablement autre chose également.
Dougal

J'ai essayé ce que vous avez suggéré et j'ai obtenu différents ensembles de coefficients: [-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]pour sklearnet [-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]pour glmnetdans l'ordre de [Intercept, rank_2, rank_3, rank_4, gre, gpa]. Ce qui m'inquiète, c'est qu'ils diffèrent à la fois en ampleur et en affectant positivement / négativement la probabilité, donc sans savoir pourquoi ils diffèrent, il est difficile de choisir celui sur lequel interpréter. Et s'il y a par hasard un bogue dans l'une des implémentations, il est particulièrement important que je sache sur lequel s'appuyer.
hurrikale

7

La réponse de Dougal est correcte, vous régularisez l'interception dans sklearnmais pas dans R. Assurez-vous que vous utilisez solver='newton-cg'car solver par défaut ( 'liblinear') régularise toujours l'interception.

cf https://github.com/scikit-learn/scikit-learn/issues/6595


Réglage solver='newton-cg'fait les résultats de sklearnet statsmodelscohérente. Merci beaucoup.
irene

0

Vous devez également utiliser l' L1_wt=0argument avec alphain fit_regularized()call.

Ce code dans statsmodels:

import statsmodels.api as sm
res = sm.GLM(y, X, family=sm.families.Binomial()).fit_regularized(alpha=1/(y.shape[0]*C), L1_wt=0)

est équivalent au code suivant de sklearn:

from sklearn import linear_model
clf = linear_model.LogisticRegression(C = C)
clf.fit(X, y)

J'espère que cela aide!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.