首先,有一些小事情:
- Both
nls(...)
and nls.lm(...)
需要数字参数,而不是日期。所以你必须以某种方式进行转换。我刚刚添加了一个days
列是自数据开始以来的天数。
- 您的 F 方程与方程不同。 1 在参考文献中,所以我将其更改为对齐。
*
f <- function(pars, xx)
with(pars,(a + (tc - xx)^m * (b + c * cos(omega*log(tc - xx) + phi))))
现在主要问题是:您的初始估计导致 LM 回归无法收敛。结果,值在nls.out$par
不是稳定的估计。当您使用这些作为起点时nls(...)
,也失败了:
nls.out <- nls.lm(par=list(a=1,b=-1,tc=5000, m=0.5, omega=1, phi=1, c=1 ),
fn = resids, observed = df$Y, xx = df$days)
# Warning messages:
# 1: In log(pars$tc - xx) : NaNs produced
# 2: In log(pars$tc - xx) : NaNs produced
# ...
# 7: In nls.lm(par = list(a = 1, b = -1, tc = 5000, m = 0.5, omega = 1, :
# lmdif: info = -1. Number of iterations has reached `maxiter' == 50.
一般来说,您应该查看nls.out$status
and nls.out$message
看看发生了什么。
您有一个包含 7 个参数的复杂模型。不幸的是,这会导致回归具有许多局部最小值的情况。因此,即使您提供导致收敛的估计,它们也可能不是“有用的”。考虑:
nls.out <- nls.lm(par=list(a=1,b=1,tc=2000, m=-1, omega=1, phi=1, c=1 ),
fn = resids, observed = df$Y, xx = df$days,
control=nls.lm.control(maxiter=10000, ftol=1e-6, maxfev=1e6))
par <- nls.out$par
par
plot(df$Date,df$Y,type="l")
lines(df$Date,f(par,df$days))
这是一个稳定的结果(局部最小值),但是c
相比之下是如此之小b
振荡是不可见的。另一方面,这些初始估计产生的拟合与参考相当接近:
nls.out <- nls.lm(par=list(a=0,b=1000,tc=2000, m=-1, omega=10, phi=1, c=200 ),
fn = resids, observed = df$Y, xx = df$days,
control=nls.lm.control(maxiter=10000, ftol=1e-6, maxfev=1e6))
这确实产生了导致收敛的参数估计nls(...)
,但总结表明参数估计很差(仅tc
and omeega
have p < 0.05
).
nls.final <- nls(Y~a+(tc-days)^m * (b + c * cos(omega * log(tc-days) + phi)),
data=df, start=par, algorithm="plinear",
control=nls.control(maxiter=1000, minFactor=1e-8))
summary(nls.final)
最后,使用非常接近参考的起始估计(诚然,这是对大萧条而不是大衰退进行建模),给出了更好的结果:
nls.out <- nls.lm(par=list(a=600,b=-266,tc=3000, m=.5,omega=7.8,phi=-4,c=-14),
fn = resids, observed = df$Y, xx = df$days,
control=nls.lm.control(maxiter=10000, ftol=1e-6, maxfev=1e6))