Ошибка nls на некоторых подмножествах данных, но не на других аналогичных подмножествах - PullRequest
1 голос
/ 15 марта 2019

Я пытаюсь применить функцию 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)

На мой взгляд, два набора данных выглядят очень похоже. Есть ли способ, которым я могу диагностировать, почему один отказывает, а другой нет? Что я могу сделать, чтобы это исправить?

Спасибо

1 Ответ

1 голос
/ 15 марта 2019

Ниже мы покажем 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

...