2012-09-29 15 views
5

यहां कोड है (मुझे खेद है कि यह बहुत लंबा है, लेकिन यह मेरा पहला उदाहरण था); मैं ए विटमैन द्वारा CreditMetrics पैकेज और DEoptim solver से Cvar उदाहरण का उपयोग कर रहा अनुकूलन करने के लिए:बाध्य ऑप्टिमाइज़ेशन में पैरामीटर 'योग 1 को कैसे सेट करें

library(CreditMetrics) 
library(DEoptim) 

N <- 3 
n <- 100000 
r <- 0.003 
ead <- rep(1/N,N) 
rc <- c("AAA", "AA", "A", "BBB", "BB", "B", "CCC", "D") 
lgd <- 0.99 
rating <- c("BBB", "AA", "B") 
firmnames <- c("firm 1", "firm 2", "firm 3") 
alpha <- 0.99 

# correlation matrix 
rho <- matrix(c( 1, 0.4, 0.6, 
        0.4, 1, 0.5, 
        0.6, 0.5, 1), 3, 3, dimnames = list(firmnames, firmnames), 
       byrow = TRUE) 

# one year empirical migration matrix from standard&poors website 
rc <- c("AAA", "AA", "A", "BBB", "BB", "B", "CCC", "D") 
M <- matrix(c(90.81, 8.33, 0.68, 0.06, 0.08, 0.02, 0.01, 0.01, 
       0.70, 90.65, 7.79, 0.64, 0.06, 0.13, 0.02, 0.01, 
       0.09, 2.27, 91.05, 5.52, 0.74, 0.26, 0.01, 0.06, 
       0.02, 0.33, 5.95, 85.93, 5.30, 1.17, 1.12, 0.18, 
       0.03, 0.14, 0.67, 7.73, 80.53, 8.84, 1.00, 1.06, 
       0.01, 0.11, 0.24, 0.43, 6.48, 83.46, 4.07, 5.20, 
       0.21,  0, 0.22, 1.30, 2.38, 11.24, 64.86, 19.79, 
       0,  0,  0,  0,  0,  0,  0, 100 
)/100, 8, 8, dimnames = list(rc, rc), byrow = TRUE) 

cm.CVaR(M, lgd, ead, N, n, r, rho, alpha, rating) 

y <- cm.cs(M, lgd)[which(names(cm.cs(M, lgd)) == rating)] 

अब मैं अपने समारोह लिखना ...

fun <- function(w) { 
    # ... 
    - (t(w) %*% y - r)/cm.CVaR(M, lgd, ead = w, N, n, r, 
          rho, alpha, rating) 
} 

... और मुझे अनुकूलित करना चाहते हैं यह:

DEoptim(fn = fun, lower = rep(0, N), upper = rep(1, N), 
     control = DEoptim.control()) 

आप मुझे बता सकते कि मैं क्या sum(w) = 1 अनुकूलन के दौरान बनाने के लिए # ... में सम्मिलित करने के लिए क्या है?

नीचे मैं flodel के सुझावों के अनुसार अनुकूलन परिणाम आपको बताएंगे:

# The first trick is to include B as large number to force the algorithm to put sum(w) = 1 

fun <- function(w) { 
    - (t(w) %*% y - r)/cm.CVaR(M, lgd, ead = w, N, n, r, rho, alpha, rating) + 
    abs(10000 * (sum(w) - 1)) 
} 

DEoptim(fn = fun, lower = rep(0, N), upper = rep(1, N), 
     control = DEoptim.control()) 

$optim$bestval 
[1] -0.05326055 

$optim$bestmem 
par1  par2  par3 
0.005046258 0.000201286 0.994752456 

parsB <- c(0.005046258, 0.000201286, 0.994752456) 

> fun(parsB) 
      [,1] 
[1,] -0.05326089 

... और ...

आप देख सकते हैं, पहली चाल है कि में बेहतर काम करता है वह एक परिणाम मिलते जो दूसरे की तुलना में छोटा है। दुर्भाग्यवश ऐसा लगता है कि वह अधिक समय लेता है।

# The second trick needs you use w <- w/sum(w) in the function itself 

fun <- function(w) { 
    w <- w/sum(w) 
    - (t(w) %*% y - r)/cm.CVaR(M, lgd, ead = w, N, n, r, rho, alpha, rating) #+ 
    #abs(10000 * (sum(w) - 1)) 
} 

DEoptim(fn = fun, lower = rep(0, N), upper = rep(1, N), 
     control = DEoptim.control()) 

$optim$bestval 
[1] -0.0532794 

$optim$bestmem 
par1   par2   par3 
1.306302e-15 2.586823e-15 9.307001e-01 

parsC <- c(1.306302e-15, 2.586823e-15, 9.307001e-01) 
parC <- parsC/sum(parsC) 

> fun(parC) 
      [,1] 
[1,] -0.0532794 

कोई टिप्पणी?

क्या मुझे "बहुत-स्टोकास्टिक" टू-ऑप्टिमाइज्ड-फ़ंक्शन की वजह से पुनरावृत्तियों की संख्या में वृद्धि करनी चाहिए?

+0

उपरोक्त "दूसरी चाल" के लिए कोड में, आप 'मजेदार' के शरीर में 'w <- w/sum (w)' जोड़ना भूल गए।क्या आप अपना कोड और परिणाम अपडेट कर सकते हैं? – flodel

+0

धन्यवाद, मैंने अभी अपडेट किया है। इन परिणामों के अनुसार सबसे अच्छी विधि क्या होगी? –

+0

धन्यवाद। ध्यान दें कि मैंने कभी भी सुझाव नहीं दिया कि अभी भी "दूसरी चाल" के रूप में लेबल किया गया है: यह गलत है और आपको इसे हटाना चाहिए। मैंने जो सुझाव दिया वह वर्तमान में "पहली चाल" और "तीसरी चाल" के रूप में लेबल किया गया है। मैंने अभी तक एक और तरीका सुझाया है: 'मजेदार' और बाहर के शरीर में 'w <- c (w, 1-sum (w)) 'का उपयोग करने के लिए, क्या आपने यह भी कोशिश की है? मुझे लगता है कि यह आखिरी विधि थोड़ा और मजबूत और तेज हो सकती है। – flodel

उत्तर

6

प्रयास करें:

w <- w/sum(w) 

और अगर DEoptim आप सर्वोत्कृष्ट समाधान देता है w* ऐसी है कि sum(w*) != 1 तो w*/sum(w*) अपने इष्टतम समाधान होना चाहिए।

एक और दृष्टिकोण अपने सभी चरों को हल करने के लिए है, लेकिन एक। हम जानते हैं कि पिछले चर का मान तो समारोह के मुख्य भाग में 1 - sum(w) होना चाहिए, है:

w <- c(w, 1-sum(w)) 

और इष्टतम समाधान DEoptim द्वारा वापस करने के लिए भी ऐसा ही: w* <- c(w*, 1-sum(w*))

दोनों समाधान की आवश्यकता आपको लगता है कि अपनी समस्या को एक unconstrained (परिवर्तनीय सीमाओं के लिए गिनती नहीं) अनुकूलन में फिर से तैयार करें ताकि DEoptim का उपयोग किया जा सके; जो आपको मूल समस्या के समाधान को पुनर्प्राप्त करने के लिए DEoptim के बाहर थोड़ा अतिरिक्त काम करने के लिए मजबूर करता है।

आपकी टिप्पणी के जवाब में, यदि आप DEoptim चाहते हैं तो आपको सही उत्तर देने के लिए (यानी एक पोस्ट-ट्रांसफॉर्मेशन की आवश्यकता के बिना), आप अपने उद्देश्य समारोह में जुर्माना लागत भी शामिल करने का प्रयास कर सकते हैं: उदाहरण के लिए B * abs(sum(w)-1) जोड़ें जहां B कुछ मनमानी बड़ी संख्या है इसलिए sum(w) को 1 पर मजबूर किया जाएगा।

+0

धन्यवाद, फ्लोडेल, वह समाधान था जिसका उपयोग मैंने किया था। लेकिन मुझे लगता है कि opitmization ouput पहले से ही 1 तक है। कुछ महीने पहले मुझे एक फ़ंक्शन उदाहरण की याद आती है जिसमें इस बाधा को फ़ंक्शन में एम्बेड किया गया था, लेकिन मैं इसे पुनर्प्राप्त करने में सक्षम नहीं हूं :( –

+0

आपके सुझाव के लिए धन्यवाद, फ़्लोडेल दुर्भाग्य से मैं बाध्य ऑप्टिमाइज़ेशन में कुशल नहीं हूं, फिर मैं आपको दिखाऊंगा कि मैंने आपके सुझावों का उपयोग करके क्या हासिल किया है। «बड़ी 'बी' चाल» अभिसरण में धीमी थी: असल में, यह 'बी' को कम करने की कोशिश की तो यह मेरे समीकरण के पहले भाग पर चला गया; पैरामीटर के 1 में सामान्यीकरण तेजी से अभिसरण की अनुमति देता है, लेकिन सामान्यीकरण के बाद, मैंने उप-इष्टतम समाधान को obatined किया। मैं आपको अपने कोड दिखाने के लिए अपने प्रश्न को संपादित करने जा रहा हूं ... –

0

मुझे लगता है कि आपको किसी से किसी भी विचलन के लिए जुर्माना जोड़ना चाहिए। अपनी न्यूनतम समस्या को +(sum(weights) - 1)^2 * 1e10 पर जोड़ें। आपको देखना चाहिए कि यह विशाल जुर्माना वजन को 1 तक पहुंचाने के लिए मजबूर करेगा!