Lars와 Glmnet은 왜 Lasso 문제에 대해 다른 솔루션을 제공합니까?


22

R 패키지 LarsGlmnetLasso 문제를 해결하는 데 사용되는 R 패키지를 더 잘 이해하고 싶습니다 . ( 변수 및 샘플의 경우, 참조 www.stanford.edu/~hastie/Papers/glmnet.pdf를 ) 3 페이지pN

나는(β0β)아르 자형+1[12나는=1(와이나는β0엑스나는β)2+λ||β||1]

따라서 동일한 장난감 데이터 세트에 둘 다 적용했습니다. 불행하게도, 두 방법은 동일한 데이터 입력에 대해 동일한 솔루션을 제공하지 않습니다. 차이점이 어디에서 오는지 아는 사람이 있습니까?

결과를 다음과 같이 얻었습니다. 일부 데이터 (8 샘플, 12 기능, Toeplitz 디자인, 모든 것을 중심으로)를 생성 한 후 Lars를 사용하여 전체 올가미 경로를 계산했습니다. 그런 다음 Lars에 의해 계산 된 람다 시퀀스 (0.5를 곱한 값)를 사용하여 Glmnet을 실행했지만 동일한 솔루션을 얻길 희망했지만 그렇지 않았습니다.

솔루션이 비슷하다는 것을 알 수 있습니다. 그러나 차이점을 어떻게 설명 할 수 있습니까? 아래에서 내 코드를 찾으십시오. 여기에 관련 질문이 있습니다 : LASSO 솔루션을 계산하기위한 GLMNET 또는 LARS? 하지만 내 질문에 대한 답변은 포함되어 있지 않습니다.

설정:

# Load packages.
library(lars)
library(glmnet)
library(MASS)

# Set parameters.
nb.features <- 12
nb.samples <- 8
nb.relevant.indices <- 3
snr <- 1
nb.lambdas <- 10

# Create data, not really important. 
sigma <- matrix(0, nb.features, nb.features)
for (i in (1:nb.features)) {
  for (j in (1:nb.features)) {
    sigma[i, j] <- 0.99 ^ (abs(i - j))
  }
}

x <- mvrnorm(n=nb.samples, rep(0, nb.features), sigma, tol=1e-6, empirical=FALSE)
relevant.indices <- sample(1:nb.features, nb.relevant.indices, replace=FALSE)
x <- scale(x)
beta <- rep(0, times=nb.features)
beta[relevant.indices] <- runif(nb.relevant.indices, 0, 1)
epsilon <- matrix(rnorm(nb.samples),nb.samples, 1)
simulated.snr <-(norm(x %*% beta, type="F")) / (norm(epsilon, type="F"))
epsilon <- epsilon * (simulated.snr / snr)
y <- x %*% beta + epsilon
y <- scale(y)

lars :

la <- lars(x, y, intercept=TRUE, max.steps=1000, use.Gram=FALSE)
co.lars <- as.matrix(coef(la, mode="lambda"))
print(round(co.lars, 4))

#          [,1] [,2] [,3]   [,4]   [,5]   [,6]    [,7]   [,8]    [,9]   [,10]
#  [1,]  0.0000    0    0 0.0000 0.0000 0.0000  0.0000 0.0000  0.0000  0.0000
#  [2,]  0.0000    0    0 0.0000 0.0000 0.1735  0.0000 0.0000  0.0000  0.0000
#  [3,]  0.0000    0    0 0.2503 0.0000 0.4238  0.0000 0.0000  0.0000  0.0000
#  [4,]  0.0000    0    0 0.1383 0.0000 0.7578  0.0000 0.0000  0.0000  0.0000
#  [5,] -0.1175    0    0 0.2532 0.0000 0.8506  0.0000 0.0000  0.0000  0.0000
#  [6,] -0.3502    0    0 0.2676 0.3068 0.9935  0.0000 0.0000  0.0000  0.0000
#  [7,] -0.4579    0    0 0.6270 0.0000 0.9436  0.0000 0.0000  0.0000  0.0000
#  [8,] -0.7848    0    0 0.9970 0.0000 0.9856  0.0000 0.0000  0.0000  0.0000
#  [9,] -0.3175    0    0 0.0000 0.0000 3.4488  0.0000 0.0000 -2.1714  0.0000
# [10,] -0.4842    0    0 0.0000 0.0000 4.7731  0.0000 0.0000 -3.4102  0.0000
# [11,] -0.4685    0    0 0.0000 0.0000 4.7958  0.0000 0.1191 -3.6243  0.0000
# [12,] -0.4364    0    0 0.0000 0.0000 5.0424  0.0000 0.3007 -4.0694 -0.4903
# [13,] -0.4373    0    0 0.0000 0.0000 5.0535  0.0000 0.3213 -4.1012 -0.4996
# [14,] -0.4525    0    0 0.0000 0.0000 5.6876 -1.5467 1.5095 -4.7207  0.0000
# [15,] -0.4593    0    0 0.0000 0.0000 5.7355 -1.6242 1.5684 -4.7440  0.0000
# [16,] -0.4490    0    0 0.0000 0.0000 5.8601 -1.8485 1.7767 -4.9291  0.0000
#         [,11]  [,12]
#  [1,]  0.0000 0.0000
#  [2,]  0.0000 0.0000
#  [3,]  0.0000 0.0000
#  [4,] -0.2279 0.0000
#  [5,] -0.3266 0.0000
#  [6,] -0.5791 0.0000
#  [7,] -0.6724 0.2001
#  [8,] -1.0207 0.4462
#  [9,] -0.4912 0.1635
# [10,] -0.5562 0.2958
# [11,] -0.5267 0.3274
# [12,]  0.0000 0.2858
# [13,]  0.0000 0.2964
# [14,]  0.0000 0.1570
# [15,]  0.0000 0.1571

lambda = (lambda_lars / 2) 인 glmnet :

glm2 <- glmnet(x, y, family="gaussian", lambda=(0.5 * la$lambda), thresh=1e-16)
co.glm2 <- as.matrix(t(coef(glm2, mode="lambda")))
print(round(co.glm2, 4))

#     (Intercept)      V1 V2 V3     V4     V5     V6      V7     V8      V9
# s0            0  0.0000  0  0 0.0000 0.0000 0.0000  0.0000 0.0000  0.0000
# s1            0  0.0000  0  0 0.0000 0.0000 0.0000  0.0000 0.0000  0.0000
# s2            0  0.0000  0  0 0.2385 0.0000 0.4120  0.0000 0.0000  0.0000
# s3            0  0.0000  0  0 0.2441 0.0000 0.4176  0.0000 0.0000  0.0000
# s4            0  0.0000  0  0 0.2466 0.0000 0.4200  0.0000 0.0000  0.0000
# s5            0  0.0000  0  0 0.2275 0.0000 0.4919  0.0000 0.0000  0.0000
# s6            0  0.0000  0  0 0.1868 0.0000 0.6132  0.0000 0.0000  0.0000
# s7            0 -0.2651  0  0 0.2623 0.1946 0.9413  0.0000 0.0000  0.0000
# s8            0 -0.6609  0  0 0.7328 0.0000 1.6384  0.0000 0.0000 -0.5755
# s9            0 -0.4633  0  0 0.0000 0.0000 4.6069  0.0000 0.0000 -3.2547
# s10           0 -0.4819  0  0 0.0000 0.0000 4.7546  0.0000 0.0000 -3.3929
# s11           0 -0.4767  0  0 0.0000 0.0000 4.7839  0.0000 0.0567 -3.5122
# s12           0 -0.4715  0  0 0.0000 0.0000 4.7915  0.0000 0.0965 -3.5836
# s13           0 -0.4510  0  0 0.0000 0.0000 5.6237 -1.3909 1.3898 -4.6583
# s14           0 -0.4552  0  0 0.0000 0.0000 5.7064 -1.5771 1.5326 -4.7298
#         V10     V11    V12
# s0   0.0000  0.0000 0.0000
# s1   0.0000  0.0000 0.0000
# s2   0.0000  0.0000 0.0000
# s3   0.0000  0.0000 0.0000
# s4   0.0000  0.0000 0.0000
# s5   0.0000 -0.0464 0.0000
# s6   0.0000 -0.1293 0.0000
# s7   0.0000 -0.4868 0.0000
# s8   0.0000 -0.8803 0.3712
# s9   0.0000 -0.5481 0.2792
# s10  0.0000 -0.5553 0.2939
# s11  0.0000 -0.5422 0.3108
# s12  0.0000 -0.5323 0.3214
# s13 -0.0503  0.0000 0.1711
# s14  0.0000  0.0000 0.1571

답변:


20

마지막으로 두 가지 방법으로 동일한 솔루션을 만들 수있었습니다! 첫 번째 문제는 glmnet이 질문에 명시된 올가미 문제를 해결하지만 lars는 목적 함수의 정규화가 약간 다르며 을 대체한다는 것 입니다. 둘째, 두 메소드 모두 데이터를 다르게 정규화하므로 메소드를 호출 할 때 정규화를 해제해야합니다. 11212

이를 재현하고 올가미 문제에 대한 동일한 솔루션을 lars 및 glmnet을 사용하여 계산할 수 있음을 확인하려면 위 코드에서 다음 행을 변경해야합니다.

la <- lars(X,Y,intercept=TRUE, max.steps=1000, use.Gram=FALSE)

la <- lars(X,Y,intercept=TRUE, normalize=FALSE, max.steps=1000, use.Gram=FALSE)

glm2 <- glmnet(X,Y,family="gaussian",lambda=0.5*la$lambda,thresh=1e-16)

glm2 <- glmnet(X,Y,family="gaussian",lambda=1/nbSamples*la$lambda,standardize=FALSE,thresh=1e-16)

1
나는 당신이 이것을 알아 낸 것이 기쁘다. 정규화 방법이 더 합리적이라고 생각하십니까? 실제로 glmnet (올가미의 경우)에서 정규화를 사용하여 더 나쁜 결과를 얻었지만 여전히 이유를 모르겠습니다.
벤 Ogorek

나는 실제로 데이터를 표준화하고 이러한 방법을 적용하고 비슷한 지 비교합니다. 효과가 작은 변수는 일반적으로 계수가 다른 것으로 보입니다
KarthikS

0

방법이 다른 모델을 사용하는 경우 분명히 다른 답변을 얻을 수 있습니다. 절편 항을 빼더라도 절입이없는 모형은 나오지 않습니다. 왜냐하면 가장 적합한 피팅 계수가 변경 될 것이고 접근하는 방식으로 변경하지 않기 때문입니다. 동일하거나 거의 같은 대답을 원할 경우 두 방법 모두에 동일한 모형을 적합시켜야합니다.


1
네, 맞습니다. 방법은 약간 다른 모델을 사용합니다. 힌트 주셔서 감사합니다. (별도의 답변으로 차이점을 더 자세히 설명하겠습니다)
Andre

-2

결과는 동일해야합니다. lars 패키지는 기본적으로 type = "lar"를 사용합니다.이 값을 type = "lasso"로 변경하십시오. 좌표 하강은 수렴을 기반으로하기 때문에 glmnet에 대해 'thresh = 1e-16'매개 변수를 낮추십시오.


2
답변 주셔서 감사합니다. 어쩌면 내가 잘못 읽었을 수도 있지만 6 년 전 Andre의 답변에 게시 된 해결책과 상충되는 것 같습니다. 말하려는 내용에 대한 자세한 설명을 포함하고 글이 올 바르고 믿어야하는 이유를 보여주기 위해 게시물을 정교하게 작성하십시오.
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.