Regressione logistica: Scikit Learn vs glmnet


15

Sto cercando di duplicare i risultati dalla sklearnlibreria di regressione logistica usando il glmnetpacchetto in R.

Dalla documentazione sullasklearn regressione logistica , sta cercando di minimizzare la funzione di costo sotto penalità l2

minw,c12wTw+Ci=1Nlog(exp(yi(XiTw+c))+1)

Dalle vignette di glmnet, la sua implementazione riduce al minimo una funzione di costo leggermente diversa

minβ,β0[1Ni=1Nyio(β0+XioTβ)-log(1+e(β0+XioTβ))]+λ[(α-1)||β||22/2+α||β||1]

Con qualche modifica nella seconda equazione e impostando α=0 ,

λminβ,β01NλΣio=1N[-yio(β0+XioTβ)+log(1+e(β0+XioTβ))]+||β||22/2

che differisce dalla sklearnfunzione di costo solo per un fattore di λ se impostato 1Nλ=C , quindi mi aspettavo la stessa stima del coefficiente dai due pacchetti. Ma sono diversi. Sto usando il set di dati da UCLA Idre esercitazione , predicendo admitbasa sulla gre, gpae rank. Ci sono 400 osservazioni, quindi con C=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

L' Routput è in qualche modo vicino alla regressione logistica senza regolarizzazione, come si può vedere qui . Mi sto perdendo qualcosa o sto facendo qualcosa ovviamente sbagliato?

Aggiornamento: ho anche provato a usare il LiblineaRpacchetto Rper condurre lo stesso processo, eppure ho ottenuto un'altra serie di stime ( liblinearè anche il risolutore 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

Aggiornamento 2: disattivando la standardizzazione in si glmnetottiene:

> 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

L'hai mai capito?
Huey,

Risposte:


8

La regressione logistica di sklearn non standardizza gli input per impostazione predefinita, il che cambia il significato del termine di regolarizzazione ; probabilmente glmnet lo fa.L2

Soprattutto perché il gretermine è su una scala più ampia rispetto alle altre variabili, questo cambierà i costi relativi dell'uso delle diverse variabili per i pesi.

Si noti inoltre che includendo un termine di intercettazione esplicito nelle funzioni, si sta regolarizzando l'intercettazione del modello. Questo generalmente non viene fatto, poiché significa che il tuo modello non è più covariante nel spostare tutte le etichette di una costante.


glmnetconsente di disattivare la standardizzazione degli input, ma i coefficienti stimati sono ancora più diversi, vedi sopra. Inoltre, ho esplicitamente incluso il termine di intercettazione sklearnperché ne glmnetinclude uno automaticamente, quindi questo per assicurarsi che l'input per entrambi i modelli sia lo stesso.
hurrikale,

2
@hurrikale Penso che glmnet probabilmente non stia regolarizzando l'intercettazione, ma sklearn lo è. Rilasciare la colonna di intercettazione Xe passare fit_intercept=True(impostazione predefinita) a LogisticRegression. Tuttavia, probabilmente sta succedendo anche qualcos'altro.
Dougal,

Ho provato quello che hai suggerito e ho ottenuto diversi set di coefficienti: [-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]per sklearne [-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]per glmnetin ordine di [Intercept, rank_2, rank_3, rank_4, gre, gpa]. La mia preoccupazione è che differiscano sia per grandezza che per influenzare positivamente / negativamente la probabilità, quindi senza sapere perché differiscono, è difficile sceglierne uno su cui interpretare. E se per caso c'è un bug in una delle implementazioni, è particolarmente importante che io sappia su quale affidarmi.
hurrikale,

7

La risposta di Dougal è corretta, regolarizzi l'intercettazione sklearnma non in R. Assicurati di usare solver='newton-cg'poiché il solutore predefinito ( 'liblinear') regolarizza sempre l'intercettazione.

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


L'impostazione ha solver='newton-cg'reso i risultati sklearne statsmodelscoerenti. Molte grazie.
Irene,

0

Dovresti anche usare l' L1_wt=0argomento insieme a alphain fit_regularized()call.

Questo codice in 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)

è equivalente al seguente codice da sklearn:

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

Spero che sia d'aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.