首页 > 解决方案 > 在 R 中翻译 matlab fminsearchbnd?

问题描述

我正在尝试将 Matlab 代码转换为 R,找到两个函数的最小误差。

这是 Matlab 代码:

erro=@(x) sum(((f14.*x(2)./(((x(1))/0.9924)+x(5))-(f14.*x(2)./(((x(1))/0.9924)+x(5))-x(3)).*exp(-(((x(1))/0.9924)+x(5))*(t-t1)))-mo).^2)./std(mo)+ sum (((f15.*x(2)./((x(1)+x(5)))-(f15.*x(2)./((x(1)+x(5)))-x(4)).*exp(-((x(1)+x(5))).*(t-t1)))-no).^2)/std(no); 

x=fminsearchbnd(erro,xo,[0 0 200 0.9 0],[])

% x = 0.0123128476186327    13.5174782795704    368.926386686419    76.4422946745777    8.28109088192835e-09

所以我首先尝试了 pracma-package,不幸的是我可以找到 fminbnd() 和 fminsearch() 函数,但没有 fminsearchbnd()。有没有办法将这两者结合起来?或者谁能​​想到不同的解决方案?我用 "method = c("L-BFGS-B") 尝试了 optim() 函数,它给了我迄今为止最好的结果。但是我想知道是否有办法在 Matlab 和 R 中获得完全相同的结果。

我对 R 的翻译:

t <- c(0.5, 1, 2, 3)
mo <- c(368.54, 374.04, 381.75, 390.92)
no <- c(76.46, 75.96, 75.14, 74.23)
f15 <- c(0.003431)  
f14 <- c(1-f15)    
xo <-  c(0.01211952, 13.30265, 368.54, 76.46, -0.000504064)


erro <- function(x){sum(((f14*x[2]/(((x[1])/0.9924)+x[5])-(f14*x[2]/(((x[1])/0.9924)+x[5])-x[3])*exp(-(((x[1])/0.9924)+x[5])*(t-t[1])))-mo)^2)/std(mo) 
  + sum (((f15*x[2]/((x[1]+x[5]))-(f15*x[2]/((x[1]+x[5]))-x[4])*exp(-((x[1]+x[5]))*(t-t[1])))-no)^2)/std(no)} 

x <- optim(xo, erro, lower = c(0, 0, 200, 0.9, 0), method = c("L-BFGS-B"))
# $par
#[1]   0.01230393  13.30265160 368.54000000  76.44231900   0.00000000

感谢您的帮助,请原谅任何错误,这是我的第一篇文章,我对matlab一无所知!;)

更新:我想将 optim-results 与 MATLAB 中的不同值进行比较,所以我尝试了:

mo <- c(322.79, 327.06, 323.11, 322.60)
no <- c(70.01023605, 64.18709552, 59.03694208, 55.83444661)
lo <- c(0.2573, 0.2525, 0.2398, 0.2388)
xo <- c(0.07856273, 24.87679, 322.79, 70.01024, 0.03182682)

我得到错误'L-BFGS-B需要'fn'的有限值'所以我将我的第一个界限从0设置为0.00001,结果是:

[1,] 1e-05 24.91 322.79 68.59785 0.09070217

但是,我的第一个值始终保持在下限,而 Matlab 的结果是:

0.05460 28.88570 324.74040 68.58710 0.03620

标签: rmatlaboptimization

解决方案


最低生活的地区非常平坦。因此,为了在 R 中获得好的结果,可以添加一个显式的数值梯度,因为使用的梯度optim()可能不够准确。在这里,我们使用“numDeriv”包中的梯度函数。

f15 <- c(0.003431); f14 <- c(1-f15)
t <- c(0.5, 1, 2, 3)

mo <- c(322.79, 327.06, 323.11, 322.60)
no <- c(70.01023605, 64.18709552, 59.03694208, 55.83444661)
lo <- c(0.2573, 0.2525, 0.2398, 0.2388)

# starting parameters
xo <- c(0.07856273, 24.87679, 322.79, 70.01024, 0.03182682)

erro <- function(x){
    sum(((f14*x[2]/(((x[1])/0.9924)+x[5])-(f14*x[2]/(((x[1])/0.9924)+x[5])-x[3])*exp(-(((x[1])/0.9924)+x[5])*(t-t[1])))-mo)^2)/sd(mo) + sum (((f15*x[2]/((x[1]+x[5]))-(f15*x[2]/((x[1]+x[5]))-x[4])*exp(-((x[1]+x[5]))*(t-t[1])))-no)^2)/sd(no)
} 

# minimum value at MATLAB solution xm
xm <- c(0.05460, 28.88570, 324.74040, 68.58710, 0.03620)
erro(xm)
## [1] 6.367856

# numerical gradient
erro_gr <- function(x) numDeriv::grad(erro, x)

s <- optim(xo, erro, gr = erro_gr,
           lower = c(1.e-07, 0, 200, 0.9, 0),
           method = c("L-BFGS-B"))
s$par;s$value
## [1] 0.08281183 28.97220 324.7395 68.58882 0.008001717
## [1] 6.367579

这甚至比 MATLAB 解决方案 6.367856 还要小,见上文。


推荐阅读