เหตุใดการถดถอยของสันเขา 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
คุณเห็นคำถามนี้หรือไม่
ดูแล

1
ใช่ แต่ฉันยังไม่ได้รับผลลัพธ์เดียวกันโดยใช้การทำให้เป็นมาตรฐาน
จอห์น

คุณช่วยโพสต์โค้ดของคุณได้ไหม?
shadowtalker

ฉันเพิ่งมีปัญหาเดียวกัน! a = data.frame (a = jitter (1:10), b = jitter (1:10), c = jitter (1:10), d = jitter (1:10), e = jitter (1:10)) , f = jitter (1:10), g = ตัวอย่าง (jitter (1:10)), y = seq (10,100,10)); coef (lm.ridge (y ~ a + b + c + d + e + f + g, a, แลมบ์ดา = 2.57)); coef (glmnet (as.matrix (a [, 1: 7]), a $ y, ครอบครัว = "gaussian", alpha = 0, lambda = 2.57 / 10)) ผลลัพธ์ที่ได้ค่อนข้างแตกต่างกันเล็กน้อยและคล้ายกันมากขึ้นเมื่อ ฉันใช้แลมบ์ดาที่สูงขึ้นมากสำหรับ glmnet
a11msp

ที่น่าสนใจ ค่าสัมประสิทธิ์ดูเหมือนจะแตกต่างกันประมาณโดยปัจจัยที่ 10
tomka

คำตอบ:


27

ความแตกต่างที่คุณกำลังสังเกตคือเนื่องจากการหารเพิ่มเติมด้วยจำนวนการสังเกต, N, ที่ GLMNET ใช้ในการทำงานตามวัตถุประสงค์และนัยว่ามาตรฐานของ Y โดยการเบี่ยงเบนมาตรฐานตัวอย่างที่แสดงด้านล่าง

12NysyXβ22+λβ22/2

เราใช้แทน1 / ( n - 1 )สำหรับs y , s y = i ( y i - ˉ y ) 21/n1/(n-1)sY

sY=Σผม(Yผม-Y¯)2n

โดยการแยกแยะด้วยความเคารพเบต้าตั้งค่าสมการให้เป็นศูนย์

XTXβ-XTYsY+ยังไม่มีข้อความλβ=0

และการหาค่าเบต้าเราได้ค่าประมาณ

β~GLMยังไม่มีข้อความET=(XTX+ยังไม่มีข้อความλผมพี)-1XTYsY

ในการกู้คืนค่าประมาณ (และค่าปรับที่สอดคล้องกัน) ในการวัดเดิมของ Y GLMNET จะทำการคูณทั้งค่าประมาณและ lambdas ด้วยและคืนผลลัพธ์เหล่านี้ให้กับผู้ใช้sY

λยูnsTd =syλ

β^GLMยังไม่มีข้อความET=sYβ~GLMยังไม่มีข้อความET=(XTX+ยังไม่มีข้อความλผมพี)-1XTY
λยูnsเสื้อd.=sYλ

เปรียบเทียบวิธีนี้กับค่ามาตรฐานของการถดถอยแบบสัน

β^=(XTX+λผมพี)-1XTY

ขอให้สังเกตว่าจะถูกปรับขนาดโดยปัจจัยพิเศษของสหประชาชาตินอกจากนี้เมื่อเราใช้หรือฟังก์ชั่นการลงโทษจะถูกปรับขนาดโดยปริยาย1 / s Y กล่าวคือเมื่อเราใช้ฟังก์ชั่นเหล่านี้จะได้รับการประมาณการค่าสัมประสิทธิ์สำหรับบางλ *เราจะมีประสิทธิภาพได้รับการประมาณการλ = λ * / s Yλpredict()coef()1/syλλ=λ/sy

ตามข้อสังเกตเหล่านี้โทษที่ใช้ในการ GLMNET จะต้องมีการปรับขนาดโดยปัจจัยของ Nsy/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 ยินดีต้อนรับสู่ CV และขอขอบคุณสำหรับการตอบคำถามเก่านี้อย่างชัดเจน
อะมีบาพูดว่า Reinstate Monica

1
ββ~

ฉันยังสังเกตเห็นด้วยว่าในส่วนที่สองที่คุณพูดว่า "ผลลัพธ์จะสรุปรวมถึงการสกัดกั้นและตัวแปร X มาตรฐาน"; สำหรับส่วนนี้หากคุณแยกการสกัดกั้นจากนั้นติดตามการคำนวณเดียวกันผลลัพธ์ของ glmnet จะแตกต่างจากการคำนวณด้วยตนเอง
user1769197

β

3

gaussianglmnet()

(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.
where sy is the standard deviation of y. Here, the penalty should have been reported as λ/sy.

What might happen is that the function first standardizes y to y0 and then minimizes

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

For the lasso (α=1), scaling η back to report the penalty as ηsy makes sense. Then for all α, ηsy has to be reported as the penalty to maintain continuity of the results across α. This probably is the cause of the problem above. This is partly due to using (2) to solve (1). Only when α=0 or α=1 there is some equivalence between problems (1) and (2) (i.e., a correspondence between the λ in (1) and the η in (2)). For any other α(0,1), problems (1) and (2) are two different optimization problems, and there is no one-to-one correspondence between the λ in (1) and the η in (2).


1
I can't see where does your answer differ from the previous one. Could you explain, please?
Firebug

1
@Firebug I wanted to shed light on why the function reports the lambda this way, which appears unnatural when viewed solely from the perspective of ridge regression, but makes sense (or has to be this way) when viewed from the perspective of the whole spectrum including both ridge and the lasso.
Chun Li
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.