J'essaie de dupliquer les résultats de sklearn
la bibliothèque de régression logistique en utilisant le glmnet
package 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
À partir des vignettes de glmnet
, sa mise en œuvre minimise une fonction de coût légèrement différente
Avec quelques ajustements dans la deuxième équation, et en fixant , λ min β , β 0 1
qui ne diffère de la sklearn
fonction 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.admit
gre
gpa
rank
#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 R
sortie 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 LiblineaR
package R
pour effectuer le même processus, et pourtant j'ai obtenu un autre ensemble d'estimations différent ( liblinear
est é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 glmnet
donne:
> 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
Réponses:
D'autant plus que votre
gre
terme 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.
la source
glmnet
permet 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 danssklearn
car il englmnet
inclut un automatiquement, c'est pour s'assurer que les entrées des deux modèles sont les mêmes.X
et passezfit_intercept=True
(par défaut) àLogisticRegression
. Mais il se passe probablement autre chose également.[-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]
poursklearn
et[-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]
pourglmnet
dans 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.La réponse de Dougal est correcte, vous régularisez l'interception dans
sklearn
mais pas dans R. Assurez-vous que vous utilisezsolver='newton-cg'
car solver par défaut ('liblinear'
) régularise toujours l'interception.cf https://github.com/scikit-learn/scikit-learn/issues/6595
la source
solver='newton-cg'
fait les résultats desklearn
etstatsmodels
cohérente. Merci beaucoup.Vous devez également utiliser l'
L1_wt=0
argument avecalpha
infit_regularized()
call.Ce code dans
statsmodels
:est équivalent au code suivant de
sklearn
:J'espère que cela aide!
la source