在 R 中为 nls 模型获取正确的起始值

机器算法验证 r 预测模型 非线性回归 幂律 nls
2022-03-27 17:36:15

我正在尝试将一个简单的幂律模型拟合到如下数据集:

mydf

rev     weeks
17906.4 1
5303.72 2
2700.58 3
1696.77 4
947.53  5
362.03  6

目标是让电力线通过并用它来预测rev未来几周的价值。一堆研究使我找到了该nls功能,我实现如下。

newMod <- nls(rev ~ a*weeks^b, data=modeldf, start = list(a=1,b=1))
predict(newMod, newdata = data.frame(weeks=c(1,2,3,4,5,6,7,8,9,10)))

虽然这适用于lm模型,但我得到一个singular gradient错误,我知道这与我的起始值ab. 我尝试了不同的值,甚至在 Excel 中绘制它,单独传递,得到一个方程,然后使用方程中的值,但我仍然得到错误。我看了一堆像这样的答案并尝试了第二个答案(无法理解第一个),但没有结果。

关于如何找到正确的起始值,我真的可以在这里使用一些帮助。或者,我可以使用什么其他功能代替 nls。

如果您想mydf轻松重新创建:

mydf <- data.frame(rev=c(17906.4, 5303.72, 2700.58 ,1696.77 ,947.53 ,362.03), weeks=c(1,2,3,4,5,6)) 
4个回答

这是非线性最小二乘模型的常见问题;如果您的起始值与最优值相差甚远,则算法可能不会收敛,即使它可能在最优值附近表现良好。

如果你从两边的对数开始并拟合一个线性模型,你会得到作为斜率和截距的估计值( 9.947 和 -2.011 )(编辑:这是自然对数)log(a)b

的起始值,一切似乎都可以正常工作:ab

 newMod <- nls(rev ~ a*weeks^b, data=mydf, start = list(a=exp(9.947),b=-2.011))
 predict(newMod, newdata = data.frame(weeks=c(1,2,3,4,5,6,7,8,9,10)))
 [1] 17919.2138  5280.7001  2584.0109  1556.1951  1050.1230   761.4947   580.3091   458.6027
 [9]   372.6231   309.4658

尝试

 newMod <- nls(rev ~ a*weeks^b, data=mydf, startlist(a=17919.2127344,b=-1.76270557120))

我被要求稍微扩展这个答案。这个问题是如此简单,我有点惊讶 nls 失败了。然而,真正的问题在于整个 R 方法和非线性模型拟合的哲学。在现实世界中,人们会将 x 缩放到介于 -1 和 1 之间,将 y 和 y 缩放到介于 0 和 1 之间(y=ax^b)。这可能足以让 nls 收敛。当然,正如 Glen 指出的那样,您可以拟合相应的对数线性模型。这依赖于这样一个事实,即存在一个使模型线性化的简单变换。通常情况并非如此。像 nls 这样的 R 例程的问题在于它们不支持重新参数化模型。在这种情况下,重新参数化很简单,只需重新缩放/重新定位 x 和 y。然而,在拟合模型后,用户将具有与原始参数不同的参数 a 和 b。虽然从这些计算原始值很简单,但另一个困难是,通常要获得这些参数估计值的估计标准偏差并不那么简单。这是通过 delta 方法完成的,该方法涉及对数似然的 Hessian 和一些导数。非线性参数估计软件应自动提供这些计算,以便轻松支持模型的重新参数化。软件应该支持的另一件事是阶段的概念。您可以考虑首先将模型与 Glen 的版本拟合为阶段 1。“真实”模型在阶段 2 中进行拟合。另一个困难是,要获得这些参数估计的估计标准偏差通常不是那么简单。这是通过 delta 方法完成的,该方法涉及对数似然的 Hessian 和一些导数。非线性参数估计软件应自动提供这些计算,以便轻松支持模型的重新参数化。软件应该支持的另一件事是阶段的概念。您可以考虑首先将模型与 Glen 的版本拟合为阶段 1。“真实”模型在阶段 2 中进行拟合。另一个困难是,要获得这些参数估计的估计标准偏差通常不是那么简单。这是通过 delta 方法完成的,该方法涉及对数似然的 Hessian 和一些导数。非线性参数估计软件应自动提供这些计算,以便轻松支持模型的重新参数化。软件应该支持的另一件事是阶段的概念。您可以考虑首先将模型与 Glen 的版本拟合为阶段 1。“真实”模型在阶段 2 中进行拟合。非线性参数估计软件应自动提供这些计算,以便轻松支持模型的重新参数化。软件应该支持的另一件事是阶段的概念。您可以考虑首先将模型与 Glen 的版本拟合为阶段 1。“真实”模型在阶段 2 中进行拟合。非线性参数估计软件应自动提供这些计算,以便轻松支持模型的重新参数化。软件应该支持的另一件事是阶段的概念。您可以考虑首先将模型与 Glen 的版本拟合为阶段 1。“真实”模型在阶段 2 中进行拟合。

我使用 AD 模型生成器拟合您的模型,它以自然的方式支持阶段。在第一阶段,只估计了一个。这使您的模型进入球场。在第二阶段,估计 a 和 b 以获得解决方案。AD 模型生成器通过 delta 方法自动计算模型参数的任何函数的标准偏差,从而促进模型的稳定重新参数化。

Levenberg-Marquardt 算法可以帮助:

modeldf <- data.frame(rev=c(17906.4, 5303.72, 2700.58 ,1696.77 ,947.53 ,362.03), weeks=c(1,2,3,4,5,6))

require(minpack.lm)
fit <- nlsLM(rev ~ a*weeks^b, data=modeldf, start = list(a=1,b=1))

require(broom)
fit_data <- augment(fit)

plot(.fitted~rev, data=fit_data)

根据我的经验,找到 NLR 模型参数起始值的一个好方法是使用进化算法。从搜索空间中随机估计的初始种群(100 个)(父母)中选择最好的 20 个(后代),并使用这些来帮助定义后续种群中的搜索。重复直到收敛。不需要梯度或粗麻布,只需 SSE 评估。如果您不太贪婪,这通常会起作用。人们经常遇到的问题是他们使用局部搜索(Newton-Raphson)来执行全局搜索的工作。与往常一样,使用正确的工具来完成手头的工作是一个问题。使用 EA 全局搜索来找到牛顿局部搜索的起始值,然后让它运行到最小值更有意义。但是,就像所有事情一样,魔鬼在细节中。