【发布时间】:2013-06-11 09:47:25
【问题描述】:
我刚才问this question。我不确定是否应该将此作为答案或新问题发布。我没有答案,但我通过在 R 中使用 nls.lm 应用 Levenberg-Marquardt 算法“解决”了这个问题,当解决方案处于边界时,我运行 trust-region-reflective 算法(TRR,在 R 中实现) 远离它。现在我有新问题了。
根据我的经验,这样做程序会达到最佳状态,并且对起始值不太敏感。但这只是一种实用的方法,可以避开我在使用 nls.lm 以及 R 中的其他优化函数时遇到的问题。我想知道为什么 nls.lm 在边界约束的优化问题上表现得这样,以及如何处理在实践中使用nls.lm 时的边界约束。
下面我举了一个例子来说明这两个问题,使用nls.lm。
- 它对起始值很敏感。
- 当某个参数到达边界时它会停止。
一个可重现的例子:焦点数据集 D
library(devtools)
install_github("KineticEval","zhenglei-gao")
library(KineticEval)
data(FOCUS2006D)
km <- mkinmod.full(parent=list(type="SFO",M0 = list(ini = 0.1,fixed = 0,lower = 0.0,upper =Inf),to="m1"),m1=list(type="SFO"),data=FOCUS2006D)
system.time(Fit.TRR <- KinEval(km,evalMethod = 'NLLS',optimMethod = 'TRR'))
system.time(Fit.LM <- KinEval(km,evalMethod = 'NLLS',optimMethod = 'LM',ctr=kingui.control(runTRR=FALSE)))
compare_multi_kinmod(km,rbind(Fit.TRR$par,Fit.LM$par))
dev.print(jpeg,"LMvsTRR.jpeg",width=480)
描述模型/系统的微分方程是:
"d_parent = - k_parent * parent"
"d_m1 = - k_m1 * m1 + k_parent * f_parent_to_m1 * parent"
左图是带有初值的模型,中间是使用“TRR”拟合的模型(类似于Matlab中的算法lsqnonlin函数),右图是使用“ LM" 与nls.lm。查看拟合参数(Fit.LM$par),您会发现一个拟合参数(f_parent_to_m1)位于边界1。如果我将一个参数M0_parent 的起始值从0.1 更改为100,那么使用nls.lm 和lsqnonlin 得到相同的结果。我有很多这样的情况。
newpars <- rbind(Fit.TRR$par,Fit.LM$par)
rownames(newpars)<- c("TRR(lsqnonlin)","LM(nls.lm)")
newpars
M0_parent k_parent k_m1 f_parent_to_m1
TRR(lsqnonlin) 99.59848 0.09869773 0.005260654 0.514476
LM(nls.lm) 84.79150 0.06352110 0.014783294 1.000000
除了上面的问题,经常会出现nls.lm返回的Hessian是不可逆的(特别是当一些参数在边界上时),所以我无法得到协方差矩阵的估计。另一方面,“TRR”算法(在 Matlab 中)几乎总是通过计算解点处的雅可比来给出估计。我认为这很有用,但我也确信 R 优化算法(我尝试过的那些)没有这样做是有原因的。我想通过使用 Matlab 计算协方差矩阵的方法来获得参数估计的标准误差来知道我是否错了。
最后一点,我在previous post 中声称,Matlab lsqnonlin 在几乎所有情况下都优于 R 的优化函数。我错了。从上面的例子可以看出,如果在 R 中也实现了,Matlab 中使用的“Trust-Region-Reflective”算法实际上更慢(有时慢得多)。但是,它仍然比 R 的基本优化算法更稳定并达到更好的解决方案。
【问题讨论】:
标签: r mathematical-optimization nls