将自起始值添加到 R 中的 nls 回归

Adding self starting values to an nls regression in R

我有现成的代码用于将 S 型曲线拟合到 R 中的数据。如何使用 selfstart(或其他方法)自动找到回归的起始值?

sigmoid = function(params, x) {
  params[1] / (1 + exp(-params[2] * (x - params[3])))
}

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

# fitting code
fitmodel <- nls(y~a/(1 + exp(-b * (x-c))), start=list(a=1,b=.5,c=25))

# visualization code
# get the coefficients using the coef function
params=coef(fitmodel)

y2 <- sigmoid(params,x)
plot(y2,type="l")
points(y)

这是非线性曲线拟合中常见(且有趣)的问题。

背景

如果我们仔细观察函数 sigmoid

,我们可以找到合理的起始值

我们首先注意到

因此对于较大的 x 值,函数接近 a。换句话说,作为 a 的起始值,我们可以选择 y 的值作为 x 最大 值。 在 R 语言中,这转换为 y[which.max(x)]

现在我们有了 a 的起始值,我们需要确定 bc 的起始值。为此,我们可以利用几何级数

并通过仅保留前两项来扩展 f(x) = y

我们现在设置a = 1(我们的初始值a),重新排列方程并在两边取对数

我们现在可以拟合 log(1 - y) ~ x 形式的线性模型以获得斜率和偏移量的估计值,这反过来又提供了 bc 的起始值。

R 实现

让我们定义一个函数,它将值 xy 和 returns 作为参数起始值的 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]))
}

根据您提供的 xy 的数据,我们得到以下起始值

start_val_sigmoid(x, y)
#$a
#[1] 1
#
#$b
#[1] 0.2027444
#
#$c
#[1] 15.01613

因为start_val_sigmoid returns一个list我们可以直接使用它的输出作为nls

中的start参数
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