nls在一些数据子集上失败,但在其他类似的子集上没有失败

问题描述 投票:1回答:1

我正在尝试按年将nls函数应用于数据,因此每年都会有一个单独的nls函数。所有年份都大致相似(指数衰减),但有些年份nls()函数失败并出现“奇异梯度”误差。

工作的数据:

good_data = data.frame(y = c(8.46,6.87,5.81,6.62,5.85,5.79,4.83,4.94,4.95,5.27,5.05,5.38,5.08,3.98),
                       x = c(2,6,6,7,7,8,9,10,12,13,14,15,16,17))

失败的数据:

bad_data = data.frame(y = c(8.99,5.86,5.32,5.74,5.41,5.04,4.66,4.52,4.18,4.66,5.38,5.46,5.21,5.37,4.89),
                      x = c(2,6,6,7,7,8,9,10,11,12,13,14,15,16,17))

尝试过nls:

fit = nls(y ~ SSasymp(x, Asym, R0, lrc), data = good_data)

在我看来,这两组数据看起来非常相似。有什么方法可以诊断为什么一个失败而另一个失败?有什么我可以做的来解决它吗?

谢谢

r nls
1个回答
1
投票

下面我们展示2种方法。如果您想自动执行此操作,您可能需要尝试直接适用,如果失败则尝试(2)如果失败则尝试(1)。如果它们都失败了,那么数据可能不会真正遵循模型,并且不适合它。

如果数据完全相似,则可以避免不同方法的迭代尝试的另一种可能性是首先拟合所有数据,然后使用其中的起始值拟合每个数据集。为此,见(3)。

1)如果先通过拟合样条添加更多点,则会收敛:

sp <- with(bad_data, spline(x, y))
fit2sp <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = sp)
fit2sp

赠送:

Nonlinear regression model
  model: y ~ SSasymp(x, Asym, R0, lrc)
   data: sp
   Asym      R0     lrc 
 5.0101 22.1915 -0.2958 
 residual sum-of-squares: 5.365

Number of iterations to convergence: 0 
Achieved convergence tolerance: 1.442e-06

2)如果数据相似,另一种方法是使用先前成功拟合的起始值。

fit1 <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = good_data)
fit2 <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = bad_data, start = coef(fit1))
fit2

赠送:

Nonlinear regression model
  model: y ~ SSasymp(x, Asym, R0, lrc)
   data: bad_data
   Asym      R0     lrc 
 4.9379 15.5472 -0.7369 
 residual sum-of-squares: 2.245

Number of iterations to convergence: 10 
Achieved convergence tolerance: 7.456e-06

下面我们绘制两个解决方案

plot(y ~ x, bad_data)
points(y ~ x, sp, pch = 20)
lines(fitted(fit2sp) ~ x, sp, col = "red")
lines(fitted(fit2) ~ x, bad_data, col = "blue", lty = 2)
legend("topright", c("data", "spline", "fit2sp", "fit2"), 
  pch = c(1, 20, NA, NA), lty = c(NA, NA, 1, 2), 
  col = c("black", "black", "red", "blue"))

3)如果所有数据足够相似,则可以起作用的另一种方法是使用来自所有数据的起始值拟合所有数据然后拟合各个数据集。

all_data <- rbind(good_data, bad_data)
fitall <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = all_data)
fit1a <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = good_data, start = coef(fitall))
fit2a <- nls(y ~ SSasymp(x, Asym, R0, lrc), data = bad_data, start = coef(fitall))

screenshot

© www.soinside.com 2019 - 2024. All rights reserved.