我前段时间问过这个问题。我不确定是否应该将此作为答案或新问题发布。我没有答案,但我通过nls.lm
在 R 中应用 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”的拟合模型(类似于Matlablsqnonlin
函数中的算法),右图是使用“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
除了上述问题,经常会出现由返回的 Hessiannls.lm
是不可逆的(特别是当某些参数在边界上时),所以我无法得到协方差矩阵的估计。另一方面,“TRR”算法(在 Matlab 中)几乎总是通过计算解点处的雅可比来给出估计。我认为这很有用,但我也确信 R 优化算法(我尝试过的那些)没有这样做是有原因的。我想知道我是否错了,通过使用 Matlab 计算协方差矩阵的方法来获得参数估计的标准误差。
最后一点,我在上一篇文章中声称,Matlablsqnonlin
在几乎所有情况下都优于 R 的优化功能。我错了。从上面的示例中可以看出,如果在 R 中也实现,则 Matlab 中使用的“信任区域反射”算法实际上更慢(有时慢得多)。但是,它仍然比 R 的基本优化算法更稳定并达到更好的解决方案。