cv.glmnet 결과의 다양성


18

cv.glmnet예측 변수를 찾는 데 사용 하고 있습니다. 내가 사용하는 설정은 다음과 같습니다.

lassoResults<-cv.glmnet(x=countDiffs,y=responseDiffs,alpha=1,nfolds=cvfold)
bestlambda<-lassoResults$lambda.min

results<-predict(lassoResults,s=bestlambda,type="coefficients")

choicePred<-rownames(results)[which(results !=0)]

메이크업에 확인 결과는 재현 I 있습니다 set.seed(1). 결과는 매우 다양합니다. 결과가 얼마나 변수인지 확인하기 위해 정확히 동일한 코드 100을 실행했습니다. 98/100 런에서 하나의 특정 예측 변수가 항상 선택되었습니다 (때로는 그 자체 만 가능합니다). 다른 예측 변수는 보통 50/100 배로 선정되었습니다 (계수는 0이 아님).

따라서 교차 검증이 실행될 때마다 폴드의 초기 무작위 화가 중요하기 때문에 아마도 다른 최상의 람다를 선택하게 될 것이라고 말합니다. 다른 사람들은이 문제 ( CV.glmnet results )를 보았지만 제안 된 해결책은 없습니다.

나는 아마도 98/100을 나타내는 것이 다른 모든 것과 매우 관련이 있다고 생각합니다. LOOCV ( fold-size = n )를 실행하면 결과 안정화 되지만 nfold < n 일 때 왜 그렇게 가변적인지 궁금 합니다.fold-size=nnfold<n


1
분명히, 당신은 set.seed(1)한 번 cv.glmnet()100 번 실행 한다는 의미 입니까? 재현성을위한 훌륭한 방법론은 아닙니다. set.seed()각 달리기 직전에 나아지 거나 달리기 동안 foldid를 일정하게 유지하십시오. 당신의 각 전화 cv.glmnet()sample()N 번 전화 입니다. 따라서 데이터 길이가 변경되면 재현성이 변경됩니다.
smci

답변:


14

여기서 중요한 점 cv.glmnet은 K 접기 ( "부품")에서 임의로 선택 한다는 것입니다 .

K- 폴드 교차 검증에서 데이터 세트는 부분 으로 나누어 지고 K - 1 부분은 K 번째 부분을 예측하는 데 사용됩니다 ( 매번 다른 K 부분을 사용하여 K 번 수행됨 ). 이것은 모든 람다에 대해 수행 되며 가장 작은 교차 유효성 검사 오류를 발생시키는 것입니다.KK1KKlambda.min

이것이 때 결과가 변경되지 않는 이유입니다. 각 그룹은 하나로 구성되므로 K 그룹에 대한 선택은 많지 않습니다 .nfolds=nK

로부터 cv.glmnet()참조 설명서 :

접기는 무작위로 선택되므로 cv.glmnet의 결과는 무작위입니다. 사용자는 cv.glmnet을 여러 번 실행하고 오류 곡선을 평균하여이 임의성을 줄일 수 있습니다.

### cycle for doing 100 cross validations
### and take the average of the mean error curves
### initialize vector for final data.frame with Mean Standard Errors
MSEs <- NULL
for (i in 1:100){
                 cv <- cv.glmnet(y, x, alpha=alpha, nfolds=k)  
                 MSEs <- cbind(MSEs, cv$cvm)
             }
  rownames(MSEs) <- cv$lambda
  lambda.min <- as.numeric(names(which.min(rowMeans(MSEs))))

MSE는 모든 람다 (100 회 실행)에 대한 모든 오류를 포함하는 데이터 프레임 lambda.min이며 최소 평균 오류가있는 람다입니다.


내가 가장 염려하는 것은 n의 선택이 실제로 중요한 것처럼 보인다는 것입니다. 가변적 인 결과를 신뢰해야합니까? 아니면 여러 번 실행해도 스케치로 분필로 그려야합니까?
user4673

1
표본 크기에 따라 n을 선택해야 그룹당 최소 10 개의 관측 값이 있습니다. 따라서 샘플 크기가 100보다 작은 경우 기본 n (= 10)을 줄이는 것이 좋습니다. 이것은 코드 조각으로 편집 된 답변을 참조하십시오.이 for 루프를 사용하면 cv.glmnet을 100 번 반복하고 평균을 오차 곡선. 몇 번 시도하면 lambda.min이 변경되지 않음을 알 수 있습니다.
Alice

2
나는 당신이 한 일을 좋아합니다. 나는 동일한 루프를 가지고 있지만 끝에 한 가지 예외가 있습니다. 모든 반복에서 가장 낮은 MSE와는 달리 다른 기능이 얼마나 자주 나타나는지 봅니다. 임의의 컷 포인트를 선택하고 (즉, 50/100 반복 표시) 해당 기능을 사용합니다. 두 가지 접근 방식이 궁금합니다.
user4673

1
이 rownames (MSE 값) <- CV의 제 경우 람다 이상 MSE 값보다 (I는 ... 그 때문에 수렴 가정)이다lambdaerror,sincecv
user4581

user4581이 지적했듯이이 함수는 길이의 가변성으로 인해 실패 할 수 있습니다 cv.glmnet(...)$lambda. 내 대안은 이것을 수정합니다 : stats.stackexchange.com/a/173895/19676
Max

9

λααλα

αλ

그런 다음 각 예측 변수에 대해 다음을 얻습니다.

  • 평균 계수
  • 표준 편차
  • 5 개의 숫자 요약 (중간 값, 사 분위수, 최소 및 최대)
  • 시간의 백분율이 0과 다릅니다 (즉, 영향을 미침)

이렇게하면 예측 변수의 효과에 대해 매우 확실하게 설명합니다. 일단 계수에 대한 분포가 있다면 CI, p 값 등을 얻을 가치가 있다고 생각되는 통계 자료를 실행할 수있는 것보다 아직 조사하지 않았습니다.

이 방법은 내가 생각할 수있는 선택 방법과 거의 비슷하게 사용할 수 있습니다.


4
여기에 코드를 게시 할 수 있습니까?
rbm

예, 코드를 여기에 게시 해 주시겠습니까?
smci

4

람다가 누락되어 @Alice의 버그를 처리하는 다른 솔루션을 추가하지만 @Max Ghenis와 같은 추가 패키지는 필요하지 않습니다. 다른 모든 답변에 감사드립니다-모두가 유용한 포인트를 만듭니다!

lambdas = NULL
for (i in 1:n)
{
    fit <- cv.glmnet(xs,ys)
    errors = data.frame(fit$lambda,fit$cvm)
    lambdas <- rbind(lambdas,errors)
}
# take mean cvm for each lambda
lambdas <- aggregate(lambdas[, 2], list(lambdas$fit.lambda), mean)

# select the best one
bestindex = which(lambdas[2]==min(lambdas[2]))
bestlambda = lambdas[bestindex,1]

# and now run glmnet once more with it
fit <- glmnet(xy,ys,lambda=bestlambda)

3

앨리스의 대답 은 대부분의 경우 잘 작동하지만 때로는 cv.glmnet$lambda다른 길이의 결과를 반환 하여 때때로 오류가 발생합니다 .

행 이름 <-(tmp, value = c (0.135739830284452, 0.12368107787663)의 오류 : 'dimnames'[1]의 길이가 배열 범위와 같지 않습니다.

OptimLambda아래는 일반적인 경우에 작동해야 mclapply하며 병렬 처리 및 루프 방지를 활용하여 더 빠릅니다 .

Lambdas <- function(...) {
  cv <- cv.glmnet(...)
  return(data.table(cvm=cv$cvm, lambda=cv$lambda))
}

OptimLambda <- function(k, ...) {
  # Returns optimal lambda for glmnet.
  #
  # Args:
  #   k: # times to loop through cv.glmnet.
  #   ...: Other args passed to cv.glmnet.
  #
  # Returns:
  #   Lambda associated with minimum average CV error over runs.
  #
  # Example:
  #   OptimLambda(k=100, y=y, x=x, alpha=alpha, nfolds=k)
  #
  require(parallel)
  require(data.table)
  MSEs <- data.table(rbind.fill(mclapply(seq(k), function(dummy) Lambdas(...))))
  return(MSEs[, list(mean.cvm=mean(cvm)), lambda][order(mean.cvm)][1]$lambda)
}

1

foldid를 명시 적으로 설정하면 임의성을 제어 할 수 있습니다. 다음은 5 중 CV의 예입니다.

library(caret)
set.seed(284)
flds <- createFolds(responseDiffs, k = cvfold, list = TRUE, returnTrain = FALSE)
foldids = rep(1,length(responseDiffs))
foldids[flds$Fold2] = 2
foldids[flds$Fold3] = 3
foldids[flds$Fold4] = 4
foldids[flds$Fold5] = 5

이제이 foldid와 함께 cv.glmnet을 실행하십시오.

lassoResults<-cv.glmnet(x=countDiffs,y=responseDiffs,alpha=1,foldid = foldids)

매번 같은 결과를 얻을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.