Чому регрес хребта glmnet дає мені іншу відповідь, ніж ручний розрахунок?


28

Я використовую glmnet для розрахунку оцінок регресії хребта. Я отримав певні результати, які змусили мене підозріти в тому, що glmnet справді робить те, що, на мою думку, це робить. Щоб перевірити це, я написав простий R-скрипт, де я порівнюю результат регресії хребта, виконаного рішенням, і той, який є в glmnet, різниця значна:

n    <- 1000
p.   <-  100
X.   <- matrix(rnorm(n*p,0,1),n,p)
beta <- rnorm(p,0,1)
Y    <- X%*%beta+rnorm(n,0,0.5)

beta1 <- solve(t(X)%*%X+5*diag(p),t(X)%*%Y)
beta2 <- glmnet(X,Y, alpha=0, lambda=10, intercept=FALSE, standardize=FALSE, 
                family="gaussian")$beta@x
beta1-beta2

Норма різниці зазвичай становить приблизно 20, що не може бути пов'язано з чисельно різними алгоритмами, я повинен робити щось не так. Які параметри я повинен встановити glmnet, щоб отримати такий самий результат, як і у хребта?


1
Ви бачили це питання ?
cdeterman

1
Так, але я все одно не отримую такого ж результату, використовуючи нормалізацію.
Іван

Чи можете ви опублікувати свій код тоді?
shadowtalker

У мене просто була така ж проблема! a = data.frame (a = тремтіння (1:10), b = тремтіння (1:10), c = тремтіння (1:10), d = тремтіння (1:10), e = тремтіння (1:10) , f = тремтіння (1:10), g = зразок (тремтіння (1:10)), y = seq (10,100,10)); кофе (lm.ridge (y ~ a + b + c + d + e + f + g, a, лямбда = 2,57)); coef (glmnet (as.matrix (a [, 1: 7]), a $ y, family = "gaussian", alpha = 0, лямбда = 2,57 / 10)) Результати досить різняться і стають набагато схожішими, коли Я використовую набагато вище лямбда для glmnet.
a11msp

Інтригуючий. Здається, коефіцієнти приблизно відрізняються на коефіцієнт 10.
tomka

Відповіді:


27

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

12NysyXβ22+λβ22/2

де ми використовуємо замість для , 1/n1/(n1)sy

sy=i(yiy¯)2n

Розмежуючи відносно бета-версії, встановлюючи рівняння на нуль,

XTXβXTysy+Nλβ=0

І вирішуючи бета, ми отримуємо оцінку,

β~GLMNET=(XTX+NλIp)1XTysy

Щоб відновити оцінки (і їх відповідні штрафні санкції) на вихідної метриці Y, GLMNET розмножується як оцінки і лямбда по і повертає ці результати до користувача,sy

β^GLMNET=syβ~GLMNET=(XTX+NλIp)1XTy
λunstd.=syλ

Порівняйте це рішення зі стандартним походженням регресії хребта.

β^=(XTX+λIp)1XTy

Зауважте, що масштабується додатковим фактором N. Крім того, коли ми використовуємо функцію або , покарання буде неявно масштабовано на . Тобто, коли ми використовуємо ці функції для отримання оцінок коефіцієнта для деяких , ми ефективно отримуємо оцінки для .λpredict()coef()1/syλλ=λ/sy

На підставі цих спостережень, покарання використовується в GLMNET має бути розширено з коефіцієнтом .sy/N

set.seed(123)

n    <- 1000
p   <-  100
X   <- matrix(rnorm(n*p,0,1),n,p)
beta <- rnorm(p,0,1)
Y    <- X%*%beta+rnorm(n,0,0.5)

sd_y <- sqrt(var(Y)*(n-1)/n)[1,1]

beta1 <- solve(t(X)%*%X+10*diag(p),t(X)%*%(Y))[,1]

fit_glmnet <- glmnet(X,Y, alpha=0, standardize = F, intercept = FALSE, thresh = 1e-20)
beta2 <- as.vector(coef(fit_glmnet, s = sd_y*10/n, exact = TRUE))[-1]
cbind(beta1[1:10], beta2[1:10])

           [,1]        [,2]
[1,]  0.23793862  0.23793862
[2,]  1.81859695  1.81859695
[3,] -0.06000195 -0.06000195
[4,] -0.04958695 -0.04958695
[5,]  0.41870613  0.41870613
[6,]  1.30244151  1.30244151
[7,]  0.06566168  0.06566168
[8,]  0.44634038  0.44634038
[9,]  0.86477108  0.86477108
[10,] -2.47535340 -2.47535340

Результати узагальнюють до включення перехоплюючих та стандартизованих змінних X. Ми модифікуємо стандартизовану матрицю X, щоб включати стовпчик з них і діагональну матрицю, щоб мати додатковий нульовий запис у позиції [1,1] (тобто не карайте перехоплення). Потім можна скасувати стандартизацію оцінок за відповідними стандартними відхиленнями вибірки (знову переконайтеся, що ви використовуєте 1 / n при обчисленні стандартного відхилення).

β^j=βj~sxj

β^0=β0~x¯Tβ^
mean_x <- colMeans(X)
sd_x <- sqrt(apply(X,2,var)*(n-1)/n)
X_scaled <- matrix(NA, nrow = n, ncol = p)
for(i in 1:p){
    X_scaled[,i] <- (X[,i] - mean_x[i])/sd_x[i] 
}
X_scaled_ones <- cbind(rep(1,n), X_scaled)

beta3 <- solve(t(X_scaled_ones)%*%X_scaled_ones+1000*diag(x = c(0, rep(1,p))),t(X_scaled_ones)%*%(Y))[,1]
beta3 <- c(beta3[1] - crossprod(mean_x,beta3[-1]/sd_x), beta3[-1]/sd_x)

fit_glmnet2 <- glmnet(X,Y, alpha=0, thresh = 1e-20)
beta4 <- as.vector(coef(fit_glmnet2, s = sd_y*1000/n, exact = TRUE))

cbind(beta3[1:10], beta4[1:10])
             [,1]        [,2]
 [1,]  0.24534485  0.24534485
 [2,]  0.17661130  0.17661130
 [3,]  0.86993230  0.86993230
 [4,] -0.12449217 -0.12449217
 [5,] -0.06410361 -0.06410361
 [6,]  0.17568987  0.17568987
 [7,]  0.59773230  0.59773230
 [8,]  0.06594704  0.06594704
 [9,]  0.22860655  0.22860655
[10,]  0.33254206  0.33254206

Додано код, щоб показати стандартизований X без перехоплення:

set.seed(123)

n <- 1000
p <-  100
X <- matrix(rnorm(n*p,0,1),n,p)
beta <- rnorm(p,0,1)
Y <- X%*%beta+rnorm(n,0,0.5)

sd_y <- sqrt(var(Y)*(n-1)/n)[1,1]

mean_x <- colMeans(X)
sd_x <- sqrt(apply(X,2,var)*(n-1)/n)

X_scaled <- matrix(NA, nrow = n, ncol = p)
for(i in 1:p){
    X_scaled[,i] <- (X[,i] - mean_x[i])/sd_x[i] 
}

beta1 <- solve(t(X_scaled)%*%X_scaled+10*diag(p),t(X_scaled)%*%(Y))[,1]

fit_glmnet <- glmnet(X_scaled,Y, alpha=0, standardize = F, intercept = 
FALSE, thresh = 1e-20)
beta2 <- as.vector(coef(fit_glmnet, s = sd_y*10/n, exact = TRUE))[-1]
cbind(beta1[1:10], beta2[1:10])

             [,1]        [,2]
 [1,]  0.23560948  0.23560948
 [2,]  1.83469846  1.83469846
 [3,] -0.05827086 -0.05827086
 [4,] -0.04927314 -0.04927314
 [5,]  0.41871870  0.41871870
 [6,]  1.28969361  1.28969361
 [7,]  0.06552927  0.06552927
 [8,]  0.44576008  0.44576008
 [9,]  0.90156795  0.90156795
[10,] -2.43163420 -2.43163420

3
+6. Ласкаво просимо до резюме та дякуємо, що відповіли на це старе питання настільки чітко.
Амеба каже: Відновити Моніку

1
Це має бути матриця ідентичності замість у розчині , правильно? ββ~
користувач1769197

Я також зауважую, що для другої частини, де ви сказали, "Результати узагальнюють включення перехоплення та стандартизованих змінних X"; для цієї частини, якщо виключаєте перехоплення, то, слідуючи тим же розрахункам, результати glmnet стають різними від ручних обчислень.
користувач1769197

Правильно, я оновив рішення за допомогою матриці ідентичності замість за потребою. Я перевірив рішення на стандартизований X без перехоплення і все одно отримую однакові результати (див. Додатковий код вище). β
skijunkie

3

Відповідно до https://web.stanford.edu/~hastie/glmnet/glmnet_alpha.html , коли сім'я gaussian, glmnet()слід мінімізувати

(1)12ni=1n(yiβ0xiTβ)2+λj=1p(α|βj|+(1α)βj2/2).

При використанні glmnet(x, y, alpha=1)для підключення ласо до стовпців у стандартизованим рішенням для повідомленого штрафу є рішення для мінімізації Однак, принаймні , при використанні для пристосування регресії хребта рішенням повідомленого штрафу є рішення мінімізації де - стандартне відхилення . Тут про покарання слід було повідомити як .xλ

12ni=1n(yiβ0xiTβ)2+λj=1p|βj|.
glmnet_2.0-13glmnet(x, y, alpha=0)λ
12ni=1n(yiβ0xiTβ)2+λ12syj=1pβj2.
syyλ/sy

Що може статися, це те, що функція спочатку стандартизує до а потім мінімізує що ефективно зводить до мінімуму або рівнозначно, щоб мінімізувати yy0

(2)12ni=1n(y0ixiTγ)2+ηj=1p(α|γj|+(1α)γj2/2),
12nsy2i=1n(yiβ0xiTβ)2+ηαsyj=1p|βj|+η1α2sy2j=1pβj2,
12ni=1n(yiβ0xiTβ)2+ηsyαj=1p|βj|+η(1α)j=1pβj2/2.

Для lasso ( ) масштабування назад, щоб повідомити про штраф, оскільки має сенс. Тоді для всіх , слід повідомити як штраф, щоб підтримувати безперервність результатів через . Це, мабуть, причина проблеми вище. Частково це пов'язано з використанням (2) для розв’язання (1). Тільки коли або існує деяка еквівалентність між завданнями (1) і (2) (тобто відповідність між в (1) і в (2)). Для будь-якого іншогоα=1ηηsyαηsyαα=0α=1ληα(0,1), задачі (1) та (2) - це дві різні проблеми оптимізації, і між в (1) та в (2) немає відповідності один на один .λη


1
Я не бачу, чим відрізняється ваша відповідь від попередньої. Не могли б ви пояснити, будь ласка?
Firebug

1
@Firebug Я хотів пролити світло на те, чому функція повідомляє лямбду таким чином, що видається неприродним, якщо дивитися виключно з точки зору регресії хребта, але має сенс (або має бути таким чином), якщо дивитися з точки зору всього спектру. включаючи і хребет, і ласо.
Чун Лі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.