2015-05-19 9 views
13

मुझे आशा है कि मेरा पुनर्निर्मित प्रश्न अब स्टैक ओवरफ्लो के मानदंडों को फिट करेगा। कृपया नीचे दिए गए उदाहरण पर विचार करें। मैं एक लॉग-लिकेलहुड फ़ंक्शन लिख रहा हूं जिसमें सीडीएफ पर वैक्टर की गणना करना सबसे अधिक समय लेने वाला हिस्सा है। उदाहरण 1 R::pnorm का उपयोग करता है, उदाहरण 2 सामान्य सीडीएफ को erfc के साथ अनुमानित करता है। जैसा कि आप देख सकते हैं कि परिणाम पर्याप्त रूप से समान हैं, ercf संस्करण थोड़ा तेज़ है।वैक्टरों पर सामान्य वितरण के सीडीएफ की गणना करने का सबसे तेज़ तरीका - आर :: pnorm बनाम erfc बनाम?

अभ्यास में (एक एमएलई के भीतर) हालांकि यह पता चला है कि ercf सटीक नहीं है, जो एल्गोरिदम को inf क्षेत्रों में चलाता है जब तक कोई बाधाओं को सटीक रूप से सेट नहीं करता है। मेरे प्रश्न:

1) क्या मुझे कुछ याद आ रही है? क्या कुछ त्रुटि हैंडलिंग (एआरएफसी के लिए) को लागू करना आवश्यक है?

2) क्या आपके पास कोड या विकल्प को गति देने के लिए कोई अन्य सुझाव है? क्या यह फॉर-लूप समांतर करने के लिए भुगतान करता है?

require(Rcpp) 
require(RcppArmadillo) 
require(microbenchmark) 

#Example 1 : standard R::pnorm 
src1 <- ' 
NumericVector ppnorm(const arma::vec& x,const arma::vec& mu,const  arma::vec& sigma, int lt, int lg) { 
int n = x.size(); 
arma::vec res(n); 
for (int i=0; i<n; i++) { 
    res(i) = R::pnorm(x(i),mu(i),sigma(i),lt,lg); 
} 
return wrap(res); 
} 
' 

#Example 2: approximation with ercf 
src2 <- ' 
NumericVector ppnorm(const arma::vec& x,const arma::vec& mu,const arma::vec& sigma, int lt, int lg) { 
int n = x.size(); 
arma::vec res(n); 
for (int i=0; i<n; i++) { 
res(i) = 0.5 * erfc(-(x(i) - mu(i))/sigma(i) * M_SQRT1_2); 
} 
if (lt==0 & lg==0) { 
    return wrap(1 - res); 
} 
if (lt==1 & lg==0) { 
    return wrap(res); 
} 
if (lt==0 & lg==1) { 
    return wrap(log(1 - res)); 
} 
if (lt==1 & lg==1) { 
    return wrap(log(res)); 
} 
} 
' 

#some random numbers 
xex = rnorm(100,5,4) 
muex = rnorm(100,3,1) 
siex = rnorm(100,0.8,0.3) 

#compile c++ functions 
func1 = cppFunction(depends = "RcppArmadillo",code=src1) #R::pnorm 
func2 = cppFunction(depends = "RcppArmadillo",code=src2) #ercf 

#run with exemplaric data 
res1 = func1(xex,muex,siex,1,0) 
res2 = func2(xex,muex,siex,1,0) 

# sum of squared errors 
sum((res1 - res2)^2,na.rm=T) 
# 6.474419e-32 ... very small 

#benchmarking 
microbenchmark(func1(xex,muex,siex,1,0),func2(xex,muex,siex,1,0),times=10000) 
#Unit: microseconds 
#expr min  lq  mean median  uq  max neval 
#func1(xex, muex, siex, 1, 0) 11.225 11.9725 13.72518 12.460 13.617 103.654 10000 
#func2(xex, muex, siex, 1, 0) 8.360 9.1410 10.62114 9.669 10.769 205.784 10000 
#my machine: Ubuntu 14.04 LTS, i7 2640M 2.8 Ghz x 4, 8GB memory, RRO 3.2.0 based on version R 3.2.0 
+0

कृपया 'ए' और 'इंड' के प्रतिनिधि उदाहरण और जिस कार्य को आप लागू करने का प्रयास कर रहे हैं, प्रदान करें। – nrussell

+2

क्या आपने [इस आरसीपीपी गैलरी पोस्ट को सबसेटिंग पर पढ़ा] [http://gallery.rcpp.org/articles/armadillo-subsetting/)? –

+0

@DirkEddelbuettel I निश्चित रूप से इन उदाहरणों को पढ़ते हैं और मुझे उम्मीद है कि मेरा प्रश्न स्पष्ट करता है कि मुझे खोज (x == 1) वाक्यविन्यास से अवगत है। मैं ऑब्जेक्ट को सहेजने के बिना एक चरण में सबसेट करना और फिर से शुरू करना चाहता था, क्योंकि मैं इस धारणा के तहत था कि यह मेरे कोड को गति देता है। अब मुझे समस्या को रोकने के लिए एक रास्ता मिला है। मैं सवाल संपादित करूंगा। – chameau13

उत्तर

5

1) ठीक है, तुम सच में उपयोग करना चाहिए आर के pnorm() अपने 0-वें उदाहरण के रूप में। आप नहीं करते हैं, आप इसे आरसीपीपी इंटरफ़ेस का उपयोग करते हैं। आर का pnorm() पहले से ही अच्छी तरह से आर-आंतरिक रूप से वेक्टरकृत है (यानी सी स्तर पर) इसलिए आरसीपीपी की तुलना में तुलनात्मक या तेज भी हो सकता है। यह इसके अलावा लाभ एनए, NaN, Inf, आदि के मामलों को कवर करने के ..

2) यदि आप MLE बारे में बात कर रहे हैं, तो करता है, और आप गति और सटीकता के बारे में चिंतित हैं, आप लगभग निश्चित रूप से नहीं बल्कि साथ काम करना चाहिए लॉगरिदम, और शायद pnorm() के साथ नहीं बल्कि dnorm()?

+1

अपने उत्तर के लिए धन्यवाद: 1) एक प्रकार की कटार Eddelbuettel की टिप्पणी से ऊपर मुझे लगता है कि pnorm की vectorized संस्करण और कोड मैं वास्तव में बाहर लिख रहा हूँ बराबर हैं। 2) मैं निश्चित रूप से लॉग का उपयोग कर रहा हूँ। शायद मैं अपनी भाषा के साथ मैला था और लिखा होगा कि यह एक लॉग-संभावना समारोह का हिस्सा बनने जा रहा है। लेकिन क्या आप इस बात की रूपरेखा कर सकते हैं कि मैं डॉनॉर्म के साथ कैसे काम कर सकता हूं और इसके क्या फायदे होंगे? एमएलई एक पदानुक्रमित आदेशित प्रोबिट मॉडल है और जब तक मैं आपकी टिप्पणी नहीं पढ़ता, मैं हमेशा इस धारणा के तहत था कि मुझे c.d.f. की आवश्यकता है। इस प्रकार इसके लिए pnorm .... – chameau13

+0

यदि आपको वास्तव में एक प्रोबिट मॉडल की आवश्यकता है तो आपको 'pnorm() 'की आवश्यकता है। OTOH, कई सांख्यिकीविदों पसंद करते हैं "डिफ़ॉल्ट" logit PROBIT करने के लिए ... एक कारण यह है कि संभावना बहुत आसान हो जाता है, अपनी ढाल, आदि सहित तो, आपकी समस्या के लिए, आप logit समाधान पहले की गणना कर सकता है (जो है एक "सस्ते" लॉग संभावना) और फिर PROBIT एक जो अधिक महंगा है के लिए "प्रारंभिक प्रारंभिक बिंदु" के रूप में इसके समाधान का उपयोग करें। मैं एक pnorm() आधारित गणना के साथ शेष की सिफारिश करेंगे। गति नुकसान 50% से भी कम समय ताकि आप क्यों ध्यान देना चाहिए है? मैं कहूंगा कि विश्वसनीयता और पोर्टेबिलिटी अधिक महत्वपूर्ण है। –

संबंधित मुद्दे

 संबंधित मुद्दे