1. ホーム
  2. r

[解決済み】Rでの関数の最適化(L-BFGS-Bでは'fn'に有限の値が必要)。

2022-01-29 23:44:09

質問

以下の関数を最適化(最大化)したい。 f1 . 私は下限と上限を使用する以下のコードを書きました。すべてのパラメータがゼロと同じかそれより大きいことが分かっており、また常に x4 以下の値 x6 . この問題をRで解決するにはどうしたらよいでしょうか? f1 .

          x1 = 0.1
          x2 = 0.1
          x3 = 2
          x4 = 10
          x5 = 2
          x6 = 30
          x7 = 1
          par = list(x1=x1, x2=x2, x3=x3, x4=x4,x5=x5, x6=x6, x7=x7)
          par1 = c(1, 1, 2, 1.5, 1, 1.5, 1)

          f1 = function(x, par){
              sum(log(exp(-(par$x7)*(par$x1*x + par$x2*x^2/2 + 
                par$x3 * (par$x4-x)^3/3+par$x5 *(x-par$x6)^3/3))))
          }

         x = seq(0, 500, length=100)
         z = c(par$x1, par$x2, par$x3, par$x4, par$x5, par$x6, par$x7)

        f2 = function(z){
            par.new = list(x1 = z[1], x2 = z[2], x3 = z[3], x4 = z[4]
           , x5 = z[5], x6 = z[6], x7 = z[7])
           f1(x, par.new)
        }

      optim(par1, f2, method = "L-BFGS-B", lower = rep(0, length(z)),
      upper = rep(Inf,length(z)),control = list(trace = 5,fnscale=-1)) 
      > optim(par1, f2, method = "L-BFGS-B", lower = rep(0, length(z)), 
        upper = rep(Inf, length(z)), control = list(trace = 5,fnscale=-1))
        N = 7, M = 5 machine precision = 2.22045e-16
        L = 0 0 0 0 0 0 0 
       X0 = 1 1 2 1.5 1 1.5 1 
       U = inf inf inf inf inf inf inf 
       At X0, 0 variables are exactly at the bounds
       Error in optim(par1, f2, method = "L-BFGS-B", lower = rep(0, length(z)),  : 
       L-BFGS-B needs finite values of 'fn'

解決方法は?

最適化のある時点で、関数が返す値が .Machine$double.xmax (これは 1.797693e+308 を実行します(私のマシンでは)。

あなたの関数 f1(...) は次のように定義されています。 sum(log(exp(...))) であり、また log(exp(z)) = z はどんなzでも使えるので、これを使えばいいのでは?

par1 = c(1, 1, 2, 1.5, 1, 1.5, 1)
x = seq(0, 500, length=100)
f1 = function(par, x){
  sum(-(par[7])*(par[1]*x + par[2]*x^2/2 + 
                           par[3] * (par[4]-x)^3/3+par[6] *(x-par[7])^3/3))
}
result <- optim(par1, f1, x=x, 
                method = "L-BFGS-B", 
                lower = rep(0, length(par1)), upper = rep(Inf,length(par1)),
                control = list(trace = 5,fnscale=-1)) 

result$par
# [1] 2.026284e-01 2.026284e-01 8.290126e+08 0.000000e+00 1.000000e+00 9.995598e+35 2.920267e+27
result$value
# [1] 2.423136e+147

なお、パラメータのベクトル( par ) は、必ず 第一 への引数です。 f1 .