【问题标题】:How to set parameters' sum to 1 in constrained optimization如何在约束优化中将参数的总和设置为 1
【发布时间】:2012-09-21 05:40:15
【问题描述】:

这是代码(很抱歉,如果它太长,但这是我的第一个示例);我正在使用 A. Wittmann 和 DEoptim 求解器的 CreditMetrics 包中的 CVaR 示例进行优化:

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的tips给大家展示一下优化结果:

# 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

有什么意见吗?

我是否应该因为“过于随机”而无法优化函数而增加迭代次数?

【问题讨论】:

  • 在上面“第二招”的代码中,您忘记在fun 的正文中添加w &lt;- w / sum(w)。你能更新你的代码和结果吗?
  • 谢谢,我刚刚更新了。根据这些结果,最好的方法是什么?
  • 谢谢。请注意,我从未建议过仍被标记为“第二招”的内容:这是错误的,您应该删除它。我建议的是目前被标记为“第一招”和“第三招”的东西。我建议了另一种方法:在fun的主体和外部使用w &lt;- c(w, 1-sum(w)),你也尝试过吗?我认为最后一种方法可能更健壮、更快。
  • 你说得对,我删错了。我忘记了,将变量的上限设置为 1,而不在函数体中插入 w &lt;- w / sum(w) 会给我错误的结果。
  • 关于w &lt;- c(w, 1-sum(w)),它返回给我t(w) %*% y 中数组不一致参数的错误。

标签: r optimization constraints


【解决方案1】:

试试:

w <- w / sum(w)

如果DEoptim 给你一个最优解w* 这样sum(w*) != 1 那么w*/sum(w*) 应该是你的最优解。

另一种方法是解决除一个变量之外的所有变量。我们知道最后一个变量的值一定是1 - sum(w) 所以在函数体中,有:

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

DEoptim返回的最优解做同样的事情:w* &lt;- c(w*, 1-sum(w*))

这两种解决方案都要求您将问题重新表述为无约束(不计算变量界限)优化,以便可以使用DEoptim;这迫使您在 DEoptim 之外做一些额外的工作来恢复原始问题的解决方案。

在回复您的评论时,如果您希望 DEoptim 立即为您提供正确答案(即无需进行后期转换),您还可以尝试在您的目标函数中包含惩罚成本:对于例如添加B * abs(sum(w)-1),其中B 是任意大数,因此sum(w) 将被强制为1

【讨论】:

  • 谢谢你,弗洛德尔,这是我习惯的解决方案。但我希望优化输出的总和已经为 1。几个月前,我记得一个函数示例,它在函数本身中嵌入了这个约束,但我无法恢复它:(
  • 感谢您的建议,弗洛德尔。不幸的是,我不擅长约束优化,那么我将向您展示我使用您的建议获得的结果。 «大B技巧»收敛速度较慢:事实上,它试图最小化B然后它继续我的等式的第一部分;将参数归一化为 1 允许更快的收敛,但在归一化之后,我获得了次优解决方案。我将编辑我的问题,以便向您展示我的代码...
【解决方案2】:

我认为你应该对任何偏离其中的行为加罚。 将术语+(sum(weights) - 1)^2 * 1e10 添加到您的最小化问题中。您应该看到,这个巨大的惩罚将迫使权重总和为 1!

【讨论】:

    猜你喜欢
    • 2012-12-08
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多