Логістична регресія: Scikit Learn vs glmnet


15

Я намагаюся дублювати результати з sklearnлогістичної регресійної бібліотеки за допомогою glmnetпакету в Р.

sklearn

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

З віньєток з glmnetйого реалізація мінімізує дещо інший вартість функції

minβ,β0-[1Ni=1Nуi(β0+хiТβ)-журнал(1+е(β0+хiТβ))]+λ[(α-1)||β||22/2+α||β||1]

З деяким настроєм у другому рівнянні та встановленням ,λ хв βα=0

λхвβ,β01Nλi=1N[-уi(β0+хiТβ)+журнал(1+е(β0+хiТβ))]+||β||22/2

який відрізняється від sklearnфункції вартості лише коефіцієнтом якщо set , тому я очікував однакової оцінки коефіцієнта від двох пакетів. Але вони різні. Я використовую набір даних з UCLA Idre підручник , прогнозуючи на основі , і . Є 400 спостережень, тому при , .λ1Nλ=СadmitgregparankС=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

RВихід як - то близько до логістичної регресії без регуляризації, як можна побачити тут . Я щось пропускаю чи роблю щось, очевидно, неправильне?

Оновлення: Я також намагався використовувати LiblineaRпакет Rдля проведення того ж процесу, і все ж отримав інший набір оцінок ( liblinearтакож вирішувач 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

Оновлення 2: вимкнення стандартизації glmnetдає:

> 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

Ви коли-небудь це розуміли?
Huey

Відповіді:


8

L2

Тим більше, що ваш greтермін настільки масштабний, ніж інші змінні, це змінить відносні витрати на використання різних змінних для ваг.

Зауважте також, що, включивши в функції функції явного перехоплення, ви регулюєте перехоплення моделі. Це, як правило, не робиться, оскільки це означає, що ваша модель вже не є коваріантною для переміщення всіх міток на постійну.


glmnetдозволяє вимкнути стандартизацію входів, але розрахункові коефіцієнти ще більше відрізняються, будь ласка, дивіться вище. Крім того, я чітко включив термін перехоплення, sklearnоскільки glmnetвключає його автоматично, так що це потрібно, щоб переконатися, що вхідні дані для обох моделей однакові.
урарикале

2
@hurrikale Я думаю, що glmnet, ймовірно, не регулює перехоплення, але sklearn є. Відкиньте стовпчик перехоплення Xі перейдіть fit_intercept=True(за замовчуванням) до LogisticRegression. Але, мабуть, щось інше теж відбувається.
Дугал

Я спробував те, що ви запропонували, і все ж отримав різні набори коефіцієнтів: [-1.873, -0.0606, -1.175, -1.378, 0.00182, 0.2435]для sklearnі [-2.8181, 0.0001269, -0.0002259, -0.00020288, 0.00344, 0.000188]для glmnetпорядку [Intercept, rank_2, rank_3, rank_4, gre, gpa]. Мене хвилює те, що вони різняться як за величиною, так і тим, що позитивно / негативно впливають на ймовірність, тому, не знаючи, чому вони відрізняються, важко обрати інтерпретацію. І якщо якимось випадком з’явиться помилка в одній із реалізацій, особливо важливо, щоб я знав, на яку слід покластися.
урарикале

7

Відповідь Дугаля правильна, ви регулюєте перехоплення в, sklearnале не в R. Переконайтеся, що ви використовуєте, solver='newton-cg'оскільки solver ( 'liblinear') за замовчуванням завжди регулює перехоплення.

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


Встановлення solver='newton-cg'робило результати sklearnі statsmodelsпослідовними. Дуже дякую.
Ірен

0

Ви також повинні використовувати L1_wt=0аргумент разом з alphain fit_regularized()call.

Цей код у 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)

еквівалентний наступному коду від sklearn:

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

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.