Cv.glmnet sonuçlarında değişkenlik


18

cv.glmnetÖngörüleri bulmak için kullanıyorum . Kullandığım kurulum aşağıdaki gibidir:

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

Sonuçların tekrarlanabilir olduğundan emin olmak için I set.seed(1) . Sonuçlar oldukça değişkendir. Sonuçların ne kadar değişken olduğunu görmek için aynı kodu 100 koştum. 98/100 çalışmalarında her zaman belirli bir öngörücü seçildi (bazen sadece kendi başına); diğer belirleyiciler genellikle 50/100 kez seçildi (eş-etkin sıfır değildi).

Bu yüzden bana çapraz doğrulama her çalıştığında muhtemelen farklı bir en iyi lambda seçeceğini söylüyor, çünkü kıvrımların ilk randomizasyonu önemli. Diğerleri bu sorunu gördü ( CV.glmnet sonuçları ), ancak önerilen bir çözüm yok.

Ben belki 98/100 gösteren biri muhtemelen diğerleriyle oldukça yüksek ilişkili olduğunu düşünüyorum? Sonuçlar do Sadece (LOOCV çalıştırırsanız stabilize ), ancak bunlar değişken yüzden neden merak ediyorum nfold < n .fold-size=nnfold<n


1
Açık olmak gerekirse, bir set.seed(1)kez cv.glmnet()100 kez koştun mu demek istiyorsun ? Bu tekrarlanabilirlik için mükemmel bir metodoloji değildir; set.seed()her çalışmadan önce sağa doğru daha iyi , ya da katları çalışma boyunca sabit tutun. İçin yaptığınız aramaların her biri N kez cv.glmnet()arıyor sample(). Dolayısıyla, verilerinizin uzunluğu değişirse, yeniden üretilebilirlik değişir.
smci

Yanıtlar:


14

Buradaki nokta şu ki cv.glmnet , K kıvrımlarında ("parçalar") rastgele seçilmesidir.

K katlama çapraz doğrulamasında veri seti kısımlarına bölünür ve K - 1 kısımlar K-parçasını tahmin etmek için kullanılır (bu, her seferinde farklı bir K parçası kullanılarak K kez yapılır ). Bu tüm lambdalar için yapılır ve en küçük çapraz doğrulama hatasını veren odur .KK1KKlambda.min

Bu nedenle kullandığınızda sonuçlar değişmez: her grup bir gruptan oluşur, bu nedenle K grupları için fazla seçenek yoktur .nfolds=nK

Gönderen cv.glmnet()referans kılavuzu:

Ayrıca, kıvrımlar rastgele seçildiğinden cv.glmnet sonuçlarının rasgele olduğunu unutmayın. Kullanıcılar, cv.glmnet komutunu birçok kez çalıştırarak ve hata eğrilerinin ortalamasını alarak bu rastgele özelliği azaltabilir.

### 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'ler, tüm lambdalar için tüm hataları içeren veri çerçevesidir (100 çalışma için), lambda.minminimum ortalama hata ile lambdadır.


En çok endişelendiğim şey, n seçiminin bazen bazen önemli olduğu. Bu kadar değişken olabilecek sonuçlara güvenmeli miyim? Yoksa birden çok kez çalıştırsam bile kabataslak olarak tebeşirlemeli miyim?
user4673

1
Örnek büyüklüğüne bağlı olarak, n'yi seçmelisiniz, böylece grup başına en az 10 gözleminiz olur. 100'den küçük bir örneklem boyutuna sahipseniz varsayılan n'yi (= 10) azaltmak daha iyidir. hata eğrileri. Birkaç kez deneyin ve lambda.min'in değişmeyeceğini göreceksiniz.
Alice

2
Nasıl yaptığını seviyorum. Ben aynı döngü var ama sonunda bir istisna dışında: Ben tüm yinelemeler en düşük MSE aksine ne kadar sık ​​farklı özellikler açılır bakın. Rasgele bir kesme noktası seçiyorum (yani 50/100 yineleme gösteriyor) ve bu özellikleri kullanıyorum. Meraklı iki yaklaşım kontrast.
user4673

1
lbirmbdbirerrÖr,sbenncecv

User4581'in belirttiği gibi, bu işlev, uzunluktaki değişkenlik nedeniyle başarısız olabilir cv.glmnet(...)$lambda. Alternatifim bunu düzeltir: stats.stackexchange.com/a/173895/19676
Max Ghenis

9

Son zamanlarda aynı problemle karşılaştım. Veri setimdeki 100, 200, 1000 gibi CV'yi en iyi şekilde tekrarlamaya çalıştım.λ ve α(elastik ağ kullanıyorum). Ama her biri için minimum MSE'lerin ortalamasını alan 1000 yinelemeli 3 cv testi oluştursam bileα, 3 farklı iyi alıyorum (λ, α) çiftler.

Dokunmayacağım α Burada problemim var ama en iyi çözümümün minimum MSE'lerin ortalamasını değil, bunun yerine her yineleme için en iyi katsayıları çıkarmaya karar verdim. λ ve sonra bunları değerlerin dağılımı (rastgele bir değişken) olarak ele alır.

Sonra, her bir tahminci için:

  • ortalama katsayı
  • standart sapma
  • 5 sayı özeti (medyan, çeyrekler, min. Ve maks.)
  • yüzde oranı sıfırdan farklıdır (yani bir etkisi vardır)

Bu şekilde öngörücünün etkisinin oldukça sağlam bir tanımını alırım. Katsayılar için dağılımınız olduğunda, CI, p değerleri vb. Elde etmeye değer olduğunu düşündüğünüz herhangi bir istatistiksel şeyi çalıştırabileceğinizden daha fazla ... ama henüz araştırmadım.

Bu yöntem aşağı yukarı düşünebildiğim herhangi bir seçim yöntemi ile kullanılabilir.


4
Kodunuzu buraya gönderebilir misiniz lütfen?
rbm

Evet, kodunuzu buraya gönderebilir misiniz?
smci

4

Lamdas eksikliğinden dolayı @ Alice'in hatasını işleyen ancak @Max Ghenis gibi ekstra paketler gerektirmeyen başka bir çözüm ekleyeceğim. Diğer tüm cevaplara teşekkür ederiz - herkes faydalı puanlar verir!

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

Alice'in cevabı çoğu durumda iyi çalışır, ancak bazen cv.glmnet$lambdafarklı uzunluktaki sonuçlar döndürüldüğünden kaynaklanan hatalar , örneğin:

Çaylak isimlerindeki hata <- (tmp, değer = c (0.135739830284452, 0.12368107787663,: 'dimnames' [1] uzunluğu dizi boyutuna eşit değil.

OptimLambdaaşağıda genel durumda çalışmalı mclapplyve döngülerin paralel işlenmesi ve önlenmesi için de daha hızlıdır .

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

Açık bir şekilde katlanmış olarak ayarladıysanız rasgeleliği kontrol edebilirsiniz. İşte 5 kat CV için bir örnek

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

Şimdi bu katlamalarla cv.glmnet'i çalıştırın.

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

Her seferinde aynı sonuçları alacaksınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.