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 बार।

तो यह मेरे लिए कहता है कि हर बार जब क्रॉस वैधीकरण चल रहा होता है, तो यह संभवत: एक अलग सर्वश्रेष्ठ लैंबडा का चयन करने वाला होता है, क्योंकि सिलवटों के प्रारंभिक यादृच्छिकरण की बात होती है। अन्य लोगों ने इस समस्या ( CV.glmnet परिणाम ) को देखा है, लेकिन इसका कोई हल नहीं है।

मैं सोच रहा हूं कि शायद जो 98/100 को दिखाता है वह संभवतः सभी अन्य लोगों के साथ बहुत अधिक सहसंबद्ध है? परिणाम है को स्थिर करता है, तो मैं सिर्फ LOOCV चलाने ( fold-size=n ), लेकिन मैं उत्सुक हूँ क्यों वे इतने चर जब हैं nfold<n


1
स्पष्ट होने के लिए, क्या आपका मतलब है कि आप set.seed(1)एक बार फिर cv.glmnet()100 बार दौड़ें ? यह प्रतिलिपि प्रस्तुत करने योग्यता के लिए महान पद्धति नहीं है; set.seed()प्रत्येक रन से पहले सही करना बेहतर है , वरना रनों के पार गुना स्थिर रखें। आपका प्रत्येक कॉल N बार कॉल कर रहा cv.glmnet()है sample()। इसलिए यदि आपके डेटा की लंबाई कभी बदलती है, तो प्रजनन क्षमता बदल जाती है।
2:24 बजे

जवाबों:


14

यहाँ मुद्दा यह है कि cv.glmnetK सिलवटों ("भागों") में बेतरतीब ढंग से उठाया जाता है।

K- सिलवटों में वैधीकरण क्रॉस को भागों में बांटा गया है , और K - 1 भाग का अनुमान लगाने के लिए K - 1 भागों का उपयोग किया जाता है (यह 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))))

MSEs वह डेटा फ्रेम है जिसमें सभी लंबों (100 रन के लिए) के लिए सभी त्रुटियां हैं, lambda.minन्यूनतम लंबित त्रुटि वाला आपका लैम्ब्डा है।


मुझे सबसे ज्यादा चिंता इस बात की है कि n का चयन वास्तव में कभी-कभी महत्वपूर्ण होता है। क्या मुझे ऐसे परिणामों पर भरोसा करना चाहिए जो इतने परिवर्तनशील हो सकते हैं? या मुझे इसे कई बार चलाने पर भी स्केच के रूप में चाक करना चाहिए?
user4673

1
नमूना आकार के आधार पर आपको n चुनना चाहिए ताकि आपके पास प्रति समूह कम से कम 10 अवलोकन हों। इसलिए डिफ़ॉल्ट एन (= 10) को कम करने के लिए बेहतर है यदि आपके पास नमूना आकार 100 से छोटा है। यह कहा गया है, कोड के टुकड़े के साथ संपादित उत्तर देखें: लूप के लिए आप 100 बार cv.glmnet दोहरा सकते हैं और औसत कर सकते हैं। त्रुटि घटती है। इसे कुछ बार आज़माएँ और आप देखेंगे कि lambda.min अभ्यस्त परिवर्तन नहीं होगा।
ऐलिस

2
मुझे पसंद है कि आपने इसे कैसे किया है। मेरे पास एक ही लूप है, लेकिन अंत में एक अपवाद के साथ: मैं देखता हूं कि सभी पुनरावृत्तियों से सबसे कम एमएसई के विपरीत कितनी बार अलग-अलग विशेषताएं पॉप अप होती हैं। मैं एक मनमाना कट प्वाइंट चुनता हूं (यानी 50/100 पुनरावृत्तियों को दिखाता हूं) और उन सुविधाओं का उपयोग करता हूं। दो दृष्टिकोणों के विपरीत जिज्ञासु।
उपयोगकर्ता 4673

1
यह rownames (एमएसई) <- सीवी मेरे मामले में लैम्ब्डा एमएसई से अधिक समय (मैं अपने अभिसरण के कारण मान ...) हैlambdaerror,sincecv
user4581

जैसा कि user4581 ने उल्लेख किया है, यह फ़ंक्शन लंबाई में परिवर्तनशीलता के कारण विफल हो सकता है cv.glmnet(...)$lambda। मेरा वैकल्पिक समाधान इसे ठीक करता है: सांख्यिकी.stackexchange.com/a/173895/19676
मैक्स गनीस

9

λααλα

αλ

फिर, प्रत्येक भविष्यवक्ता के लिए मुझे:

  • गुणांक का मतलब है
  • मानक विचलन
  • 5 नंबर सारांश (माध्यिका, चतुर्थक, न्यूनतम और अधिकतम)
  • समय का प्रतिशत शून्य से भिन्न होता है (अर्थात इसका प्रभाव है)

इस तरह मुझे भविष्यवक्ता के प्रभाव का बहुत ठोस वर्णन मिलता है। एक बार जब आपके पास गुणांक के लिए वितरण होते हैं, तो आप जितना भी सोचते हैं कि आप किसी भी सांख्यिकीय सामान को चला सकते हैं, सीआई, पी मान आदि प्राप्त करने के लिए लायक है ... लेकिन मैंने अभी तक इसकी जांच नहीं की है।

इस पद्धति का उपयोग कम या ज्यादा किसी भी चयन विधि के साथ किया जा सकता है, जिसके बारे में मैं सोच सकता हूं।


4
क्या आप कृपया अपना कोड यहाँ पोस्ट कर सकते हैं?
आरबीएम

हाँ, क्या आप अपना कोड यहाँ पोस्ट कर सकते हैं?
बजे

4

मैं एक और समाधान जोड़ दूंगा, जो कि @ एलिस के लापता लैम्ब्डा के कारण बग को संभालता है, लेकिन @ मैक्स रेनीस जैसे अतिरिक्त पैकेज की आवश्यकता नहीं है। धन्यवाद अन्य सभी उत्तरों के लिए बकाया हैं - हर कोई उपयोगी बिंदु बनाता है!

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

यदि आप स्पष्ट रूप से तह लगाते हैं तो आप यादृच्छिकता को नियंत्रित कर सकते हैं। यहां 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

अब इन फोल्ड के साथ cv.glmnet चलाएं।

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

आपको हर बार एक ही परिणाम मिलेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.