2011-08-22 11 views
7

मैंने कई सीटीआर मॉडल (लगभग 40 से 80) ​​बनाए हैं जिन्हें मैं अक्सर मूल्यांकन करना चाहता हूं।पार्टी ::: ctree मॉडल से प्रशिक्षण डेटा कैसे निकालें?

एक मुद्दा यह है कि मॉडल ऑब्जेक्ट्स बहुत बड़े हैं (40 मॉडल को स्मृति की 2.8 जी से अधिक की आवश्यकता होती है) और ऐसा लगता है कि उन्होंने प्रशिक्षण डेटा संग्रहीत किया, शायद मॉडल नाम @ डेटा और मॉडल नाम @ प्रतिक्रियाओं के रूप में, और नहीं नए डेटा की भविष्यवाणी करने के लिए प्रासंगिक सूचनाएं।

अधिकांश अन्य आर सीखने के पैकेज में कॉन्फ़िगर करने योग्य विकल्प हैं मॉडल मॉडल में डेटा शामिल करना है, लेकिन मुझे दस्तावेज़ में कोई संकेत नहीं मिला। मैंने

[email protected] <- new("ModelEnv") 

द्वारा खाली ModelEnv ऑब्जेक्ट्स को असाइन करने का भी प्रयास किया लेकिन संबंधित आरडीएटा फ़ाइल के आकार पर कोई प्रभाव नहीं पड़ा।

कोई भी जानता है कि सीटीआर वास्तव में प्रशिक्षण डेटा संग्रहीत करता है और सीटीरी मॉडल से सभी डेटा को कैसे हटाया जाए जो नई भविष्यवाणियों के लिए अप्रासंगिक हैं ताकि मैं उनमें से कई को स्मृति में फिट कर सकूं?

धन्यवाद एक बहुत,

स्टीफन


आपकी प्रतिक्रिया के लिए धन्यवाद, कि पहले से ही काफी मददगार था।

मैं dput और str इस्तेमाल किया वस्तु पर एक गहरी नज़र डालना और पाया कि कोई प्रशिक्षण डाटा मॉडल में शामिल है, लेकिन वहाँ एक responses स्लॉट है, जो प्रशिक्षण लेबल और rownames के लिए लगता है। वैसे भी, मैंने देखा कि प्रत्येक नोड में प्रत्येक प्रशिक्षण नमूने के लिए वजन वेक्टर होता है। कोड निरीक्षण के थोड़ी देर के बाद, मैं थोड़ा googling समाप्त हो गया और party समाचार लॉग में निम्न टिप्पणी पाया:

  CHANGES IN party VERSION 0.9-13 (2007-07-23) 

o update `mvt.f' 

o improve the memory footprint of RandomForest objects 
    substancially (by removing the weights slots from each node). 

यह पता चला, वहाँ पार्टी पैकेज में एक सी समारोह इन वजन बुलाया दूर करने के लिए है R_remove_weights निम्नलिखित परिभाषा के साथ:

SEXP R_remove_weights(SEXP subtree, SEXP removestats) { 
    C_remove_weights(subtree, LOGICAL(removestats)[0]); 
    return(R_NilValue); 
} 

यह भी ठीक काम करता है:

# cc is my model object 

sum(unlist(lapply(slotNames(cc), function (x) object.size(slot(cc, x))))) 
# returns: [1] 2521256 
save(cc, file="cc_before.RData") 

.Call("R_remove_weights", [email protected], TRUE, PACKAGE="party") 
# returns NULL and removes weights and node statistics 

sum(unlist(lapply(slotNames(cc), function (x) object.size(slot(cc, x))))) 
# returns: [1] 1521392 
save(cc, file="cc_after.RData") 

आप देख सकते हैं, यह वस्तु के आकार को कम कर देता subst लगभग 2.5 एमबी से 1.5 एमबी तक।

क्या है अजीब है, हालांकि, यह है कि इसी rdata फ़ाइलों पागलपन की हद तक विशाल हैं, और उन पर कोई प्रभाव नहीं होता:

$ ls -lh cc* 
-rw-r--r-- 1 user user 9.6M Aug 24 15:44 cc_after.RData 
-rw-r--r-- 1 user user 9.6M Aug 24 15:43 cc_before.RData 

फ़ाइल Unzipping लगभग अंतरिक्ष के 100 एमबी पर कब्जा करने 2.5MB वस्तु दिखाता है:

$ cp cc_before.RData cc_before.gz 
$ gunzip cc_before.gz 
$ ls -lh cc_before* 
-rw-r--r-- 1 user user 98M Aug 24 15:45 cc_before 

कोई विचार, इसका कारण क्या हो सकता है?

+0

यदि आप एक छोटी नमूना वस्तु पर 'dput' के परिणाम पोस्ट कर सकते हैं जो मदद करेगा। यदि आप 'str' का उपयोग करते हैं तो आप देख सकते हैं कि ऑब्जेक्ट में संग्रहीत प्रशिक्षण डेटा है या नहीं। –

+0

नोट: मैंने प्रश्न को दोबारा हटा दिया और "पार्टी" लेबल हटा दिया क्योंकि यह एसओ पर अच्छी तरह परिभाषित नहीं है, निश्चित रूप से आर पैकेज तक ही सीमित नहीं है। मैंने स्मृति प्रबंधन जोड़ा क्योंकि यह प्राथमिक प्रेरणा प्रतीत होता है। – Iterator

उत्तर

5

मैं हाथ में समस्या का समाधान मिल गया, तो मैं इस सवाल का जवाब लिखना यदि किसी एक ही मुद्दा हो सकती हैं। मैं अपनी प्रक्रिया का वर्णन करूंगा, इसलिए यह थोड़ा सा जुआ हो सकता है, इसलिए मेरे साथ भालू।

कोई सुराग के साथ, मैं इस मामले में स्लॉट्स nuking और संभव के रूप में छोटे और कम से कम कुछ स्मृति को बचाने वस्तुओं को पाने के लिए वजन को हटाने, कोई ठीक मिल जाएगा के बारे में सोचा। इसलिए मैंने @data और @responses को प्रारंभ और पूर्वानुमान के रूप में हटा दिया, फिर भी उनके बिना ठीक हो गया, फिर भी। डेटा फ़ाइल आकार पर कोई प्रभाव नहीं पड़ा।

मैं दौर अन्य तरीके से चला गया और बनाया है और खाली ctree मॉडल, बस इसे में पेड़ pluging:

> library(party) 

## create reference predictions for the dataset 
> predictions.org <- treeresponse(c1, d) 

## save tree object for reference 
save(c1, "testSize_c1.RData") 

मूल वस्तु के आकार जाँच हो रही है:

$ ls -lh testSize_c1.RData 
-rw-r--r-- 1 user user 9.6M 2011-08-25 14:35 testSize_c1.RData 

अब, चलो एक खाली सीटीटी बनाएं और केवल पेड़ की प्रतिलिपि बनाएँ:

## extract the tree only 
> c1Tree <- [email protected] 

## create empty tree and plug in the extracted one 
> newCTree <- new("BinaryTree") 
> [email protected] <- c1Tree 

## save tree for reference 
save(newCTree, file="testSize_newCTree.RData") 

यह नया पेड़ वस्तु अब बहुत छोटा है एर:

$ ls -lh testSize_newCTree.RData 
-rw-r--r-- 1 user user 108K 2011-08-25 14:35 testSize_newCTree.RData 

हालांकि, यह भविष्यवाणी करने के लिए इस्तेमाल नहीं किया जा सकता है:

## predict with the new tree 
> predictions.new <- treeresponse(newCTree, d) 
Error in [email protected]_distr_response(newdata = newdata, ...) : 
    unused argument(s) (newdata = newdata) 

हम @cond_distr_response, जो त्रुटि के कारण हो सकता सेट नहीं किया है, तो मूल एक कॉपी के साथ-साथ और करने की कोशिश फिर से भविष्यवाणी:

## extract cond_distr_response from original tree 
> cdr <- [email protected]_distr_response 
> [email protected]_distr_response <- cdr 

## save tree for reference 
save(newCTree, file="testSize_newCTree_with_cdr.RData") 

## predict with the new tree 
> predictions.new <- treeresponse(newCTree, d) 

## check correctness 
> identical(predictions.org, predictions.new) 
[1] TRUE 

यह पूरी तरह से काम करता है, लेकिन अब rdata फ़ाइल का आकार अपने मूल मूल्य पर वापस आ गया है:

$ ls -lh testSize_newCTree_with_cdr.RData 
-rw-r--r-- 1 user user 9.6M 2011-08-25 14:37 testSize_newCTree_with_cdr.RData 

आप स्लॉट मुद्रण, एक समारोह के लिए एक वातावरण के लिए बाध्य होने के लिए यह पता चलता है:

> [email protected]_distr_response 
function (newdata = NULL, mincriterion = 0, ...) 
{ 
    wh <- [email protected]_where(newdata = newdata, mincriterion = mincriterion) 
    response <- [email protected] 
    if (any([email protected]_censored)) { 
     swh <- sort(unique(wh)) 
     RET <- vector(mode = "list", length = length(wh)) 
     resp <- [email protected][[1]] 
     for (i in 1:length(swh)) { 
      w <- weights * (where == swh[i]) 
      RET[wh == swh[i]] <- list(mysurvfit(resp, weights = w)) 
     } 
     return(RET) 
    } 
    RET <- .Call("R_getpredictions", tree, wh, PACKAGE = "party") 
    return(RET) 
} 
<environment: 0x44e8090> 

तो प्रारंभिक सवाल का जवाब है कि वस्तु के तरीकों यह करने के लिए एक वातावरण बाँध प्रतीत होता है, जिसे तब संबंधित आरडीएटा फ़ाइल में ऑब्जेक्ट से सहेजा जाता है। यह भी समझा सकता है कि आरडीएटा फ़ाइल पढ़ने पर कई पैकेज क्यों लोड किए जाते हैं।

इस प्रकार, वातावरण से छुटकारा पाने के लिए, हम तरीकों कॉपी नहीं कर सकते, लेकिन हम या तो उन्हें बिना अनुमान नहीं लगा सकते। बल्कि "गंदे" समाधान मूल तरीकों की कार्यक्षमता का अनुकरण करना है और अंतर्निहित सी कोड को सीधे कॉल करना है। स्रोत कोड के माध्यम से कुछ खोदने के बाद, यह वास्तव में संभव है। चूंकि उपरोक्त कॉपी किए गए कोड से पता चलता है, हमें get_where पर कॉल करने की आवश्यकता है, जो इनपुट द्वारा प्राप्त पेड़ के टर्मिनल नोड को निर्धारित करता है। हमें प्रत्येक इनपुट नमूने के लिए उस टर्मिनल नोड से प्रतिक्रिया निर्धारित करने के लिए R_getpredictions पर कॉल करने की आवश्यकता है।

## create a character string of the formula which was used to fit the free 
## (there might be a more neat way to do this) 
> library(stringr) 
> org.formula <- str_c(
        do.call(str_c, as.list(deparse([email protected]@formula$response[[2]]))), 
        "~", 
        do.call(str_c, as.list(deparse([email protected]@formula$input[[2]])))) 

## call the internal ctree preprocessing 
> data.dpp <- party:::ctreedpp(as.formula(org.formula), d) 

## create the data object necessary for the ctree C code 
> data.ivf <- party:::initVariableFrame.df([email protected]@get("input"), 
              trafo = ptrafo) 

## now call the tree traversal routine, note that it only requires the tree 
## extracted from the @tree slot, not the whole object 
> nodeID <- .Call("R_get_nodeID", c1Tree, data.ivf, 0, PACKAGE = "party") 

## now determine the respective responses 
> predictions.syn <- .Call("R_getpredictions", c1Tree, nodeID, PACKAGE = "party") 

## check correctness 
> identical(predictions.org, predictions.syn) 
[1] TRUE 

अब हम केवल निकाले पेड़ और सूत्र स्ट्रिंग को बचाने के लिए करने की आवश्यकता है: मुश्किल बात यह है कि हम फोन करने के लिए डेटा पूर्व प्रसंस्करण ctree में शामिल है सही प्रारूप में डेटा प्राप्त है और इस तरह की जरूरत है

> .Call("R_remove_weights", c1Tree, TRUE, PACKAGE="party") 
> save(c1Tree, org.formula, file="testSize_extractedObjects__removedWeights.RData") 

आइए अब इंटरनेट पर एक नजर है:

> save(c1Tree, org.formula, file="testSize_extractedObjects.RData") 

हम आगे ऊपर अद्यतन प्रश्न में वर्णित के रूप अनावश्यक भार को दूर कर सकते हैं: नए डेटा की भविष्यवाणी करने में सक्षम le फिर से आकार:

$ ls -lh testSize_extractedObjects* 
-rw-r--r-- 1 user user 109K 2011-08-25 15:31 testSize_extractedObjects.RData 
-rw-r--r-- 1 user user 43K 2011-08-25 15:31 testSize_extractedObjects__removedWeights.RData 

अंत में, के बजाय (संपीड़ित) 9.6M, केवल 43k मॉडल का उपयोग करने के लिए आवश्यक हैं। अब मुझे अपने 3 जी हीप स्पेस में जितना चाहें उतना फिट करने में सक्षम होना चाहिए। हुर्रे!

+0

+1 यह चरण प्रस्तुति द्वारा एक महान कदम है। अच्छी नौकरी। – Iterator

1

जो आप खोज रहे हैं वह स्लॉट को निकालना है। चेतावनी का एक शब्द: यह खतरनाक हो सकता है कि party कार्य ऑब्जेक्ट के साथ कैसे काम करते हैं।

फिर भी, slotNames(yourModel) पर एक नज़र डालें। विभिन्न स्लॉट के आकार की जांच करने के लिए आप object.size(slot(yourModel), slotNameOfInterest) भी आज़मा सकते हैं। प्रत्येक स्लॉट में ऑब्जेक्ट्स के आकारों के बारे में सुनिश्चित करने के लिए आप आसानी से एक क्रमबद्ध तालिका बना सकते हैं।

किसी भी मामले में, data के लिए स्लॉट ModelEnvFormula है (मैं इसे "MEF" ऑब्जेक्ट कहूंगा)। आप एक डमी MEF बना सकते हैं: dummyMEF <- ModelEnvFormula(1 ~ 1) और फिर data: slot(yourModel, "data") <- dummyMEF पर असाइन करें।

है कि विशेष स्लॉट nuke होगा। आपको यह देखने के लिए एक नज़र रखना चाहिए कि स्टोरेज के मामले में सिरदर्द पैदा करने वाले अन्य स्लॉट हैं - object.size() फ़ंक्शन सहायता करेगा। मैं मानता हूं कि मॉडल ऑब्जेक्ट से प्रशिक्षण डेटा को छोड़ने में सक्षम होना अच्छा है।