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)]

为了确保结果是可重复我set.seed(1)。结果变化很大。我运行了完全相同的代码100,以查看结果的可变性。在98/100次运行中,总是选择一个特定的预测变量(有时仅靠预测变量);选择其他预测变量(系数非零)通常为50/100次。

因此对我来说,每次交叉验证运行时,都可能会选择一个不同的最佳lambda,因为折叠的初始随机性很重要。其他人已经看到了这个问题(CV.glmnet结果),但是没有建议的解决方案。

我在想,一个显示98/100的图像可能与所有其他图像高度相关吗?如果我只是运行LOOCV(),结果的确稳定,但是我很好奇为什么当时它们是如此可变。fold-size=nnfold<n


1
明确地说,您是说set.seed(1)一次运行cv.glmnet()100次吗?那不是重现性的好方法。最好set.seed()在每次运行之前就对它进行调整,否则在每次运行之间都应保持折叠数不变。您对的每次呼叫cv.glmnet()都呼叫sample()N次。因此,如果您的数据长度发生变化,则可重复性也会发生变化。
smci

Answers:


14

这里的重点是在cv.glmnetK折(“部分”)中随机挑选。

在K折交叉验证中,数据集分为部分,部分用于预测第K个部分(这完成了次,每次使用不同的部分)。这是针对所有lambda进行的操作,它是交叉验证误差最小的函数。KK1KKlambda.min

这就是为什么当使用结果不会改变的原因:每个组由一个组成,因此对于组没有太多选择。nfolds=nķ

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是包含所有lambda(对于100次运行)的所有错误的数据帧, lambda.min是具有最小平均错误的lambda。


我最担心的是,有时候选择n确实确实很重要。我应该相信结果会如此变化吗?还是即使我多次运行它,也应该将其绘制为草图吗?
user4673

1
根据样本量,您应该选择n,以便每个组至少有10个观察值。因此,如果样本大小小于100,最好减小默认值n(= 10)。这就是说,请参见代码段的编辑答案:使用此for循环,您可以重复cv.glmnet 100次并取平均值。误差曲线。尝试几次,您会发现lambda.min不会改变。
爱丽丝2014年

2
我喜欢你的做法。我有相同的循环,但最后有一个例外:我观察不同功能弹出的频率,而不是所有迭代中最低的MSE。我选择一个任意的切入点(即显示50/100次迭代)并使用这些功能。好奇地对比了这两种方法。
user4673 2014年

1
一种bd一种Ë[R[RØ[Rs一世ñCËCv

如user4581所述,由于的长度变化,此功能可能会失败cv.glmnet(...)$lambda。我的替代方法可解决此问题:stats.stackexchange.com/a/173895/19676
Max Ghenis

9

λααλα

αλ

然后,对于每个预测变量,我得到:

  • 平均系数
  • 标准偏差
  • 5个数字摘要(中位数,四分位数,最小值和最大值)
  • 时间百分比不为零(即具有影响力)

这样,我就可以很好地描述预测变量的效果。一旦有了系数的分布,就可以运行您认为值得获得CI,p值等的任何统计资料……但是我尚未对此进行调查。

我可以想到的这种方法几乎可以与任何选择方法一起使用。


4
您可以在这里发布您的代码吗?
rbm

是的,您能在这里发布您的代码吗?
smci

4

我将添加另一个解决方案,该解决方案可解决由于缺少lambda而导致的@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折简历的示例

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)

每次您将获得相同的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.