Это распространенная (и интересная) проблема нелинейного подбора кривой.
Фон
Мы можем найти разумные начальные значения, если более внимательно посмотреть на функцию sigmoid
Сначала отметим, что
То же для больших значений x
, функция приближается к a
. Другими словами, в качестве начального значения для a
мы можем выбрать значение y
для наибольшего значения x
. На языке R это означает y[which.max(x)]
.
Теперь, когда у нас есть начальное значение для a
, нам нужно определиться с начальными значениями для b
и c
. Для этого мы можем использовать геометрию c серии
и расширить f(x) = y
, сохранив только первые два члена
Теперь мы установим a = 1
(наше начальное значение для a
), перестроим уравнение и возьмем логарифм с обеих сторон
Теперь мы можем подобрать линейную модель вида log(1 - y) ~ x
для получения оценок наклона и смещения, которые, в свою очередь, дают начальные значения для b
и c
.
Реализация R
Давайте определим функцию, которая принимает в качестве аргумента значения x
и y
и возвращает list
начальных значений параметров
start_val_sigmoid <- function(x, y) {
fit <- lm(log(y[which.max(x)] - y + 1e-6) ~ x)
list(
a = y[which.max(x)],
b = unname(-coef(fit)[2]),
c = unname(-coef(fit)[1] / coef(fit)[2]))
}
На основании данных для x
и y
, которые вы даете, мы получаем следующие начальные значения
start_val_sigmoid(x, y)
#$a
#[1] 1
#
#$b
#[1] 0.2027444
#
#$c
#[1] 15.01613
Поскольку start_val_sigmoid
возвращает list
, мы можем использовать его выводить напрямую как аргумент start
в nls
nls(y ~ a / ( 1 + exp(-b * (x - c))), start = start_val_sigmoid(x, y))
#Nonlinear regression model
# model: y ~ a/(1 + exp(-b * (x - c)))
# data: parent.frame()
# a b c
# 1.0395 0.1254 29.1725
# residual sum-of-squares: 0.2119
#
#Number of iterations to convergence: 9
#Achieved convergence tolerance: 9.373e-06
Пример данных
dataset = data.frame("x" = 1:53, "y" =c(0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.18,0.18,0.18,0.33,0.33,0.33,0.33,0.41,0.41,0.41,0.41,0.41,0.41,0.5,0.5,0.5,0.5,0.68,0.58,0.58,0.68,0.83,0.83,0.83,0.74,0.74,0.74,0.83,0.83,0.9,0.9,0.9,1,1,1,1,1,1,1) )
x = dataset$x
y = dataset$y