R 中 nls 模型的拟合 - 手动与暴力问题

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

我试图将多个模型拟合到相同的数据,在本例中,它是双指数方法。我尝试过观察参数,并使用强力方法(见下文。

在这种情况下,手动设置参数(黑线)似乎比暴力方法(红线)更好。我不太明白为什么会这样,因为暴力法起始值中设置的参数空间包括为手动方法设置的参数。

有人可以解释为什么暴力方法不能收敛于相同的参数,或者至少有更好的拟合吗?

此外,我能否就最适合数据的建议提供建议。我尝试过 lnorm、power、exp 和 double exp。

谢谢!

# loading packages
library(nls2)
library(tidyverse)

# example dataset
df = data.frame(
  time = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 18, 21, 23, 32, 33),
  proportion = c(
    1.00000000, 0.89583333, 0.77083333, 0.58333333, 0.54166667,
    0.43750000, 0.35416667, 0.31250000, 0.25000000, 0.22916667,
    0.16666667, 0.14583333, 0.12500000, 0.10416667, 0.08333333,
    0.06250000, 0.04166667, 0.02083333, 0.00000000
  )
)


# Fitting model using manual approach
manual_fit <- nls2::nls2(proportion ~ a * exp(b * time) + c * exp(d * time),
                          data = df,
                          start = list(a = 1, b = -0.1, c = 1, d = -0.5))


# setting starting parameter space for brute approach
start_values <- list(a = seq(-.5, 1.5, length.out = 10), 
                     b = seq(-.5, 2, length.out = 10),
                     c = seq(-.5, 2, length.out = 10),
                     d = seq(-1, 2, length.out = 10))

# fitting model using brute approach
brute_fit <- nls2::nls2(proportion ~ a * exp(b * time) + c * exp(d * time), 
                                       data = df, 
                                       start = expand.grid(start_values),
                                       control = nls.control(maxiter = 2000), algorithm = "brute-force") 


# plotting to see both fits
ggplot(df) +
  geom_point(aes(x = time, y = proportion), size = 3.5) +
  geom_line(aes(x = time, y = predict(manual_fit)), linewidth = 1) +
  geom_line(aes(x = time, y = predict(brute_fit)), linewidth = 1, colour = "red") +
  ylab("Proportion > Time") +
  xlab("Time (days)")

创建于 2024-07-01,使用 reprex v2.1.0

r survival-analysis nls
1个回答
0
投票

暴力算法中没有收敛的概念。 它所做的就是评估每个点的目标,然后选择最好的。它通常用于获取起始值,然后将其输入 nls。 请注意,如果给定 2 行数据框,它将为您创建网格,如下所示。

library(nls2)

fo <- proportion ~ a * exp(b * time) + c * exp(d * time)
st <- data.frame(a = c(-0.5, 1.5), b = c(-0.5, 2), c = c(-0.5, 2), d = c(-1, 2))
fm0 <- nls2(fo, df, start = st, alg = "brute", control = list(maxiter = 10^4))

fm <- nls(fo, df, start = coef(fm0))
fm
## Nonlinear regression model
##   model: proportion ~ a * exp(b * time) + c * exp(d * time)
##    data: df
##        a        b        c        d 
##  1.00025 -0.18194  0.03566 -0.02066 
##  residual sum-of-squares: 0.008595
##
## Number of iterations to convergence: 10 
## Achieved convergence tolerance: 6.554e-06

相反,您可以尝试线性算法,该算法可用于避免线性输入参数的起始值。 这里我们使用 p线性随机与 nls2,然后使用 p线性与 nls。

set.seed(123)
fo.p <- proportion ~ cbind(a = exp(b * time), c = exp(d * time))
fm0.p <- nls2(fo.p, df, start = st[c("b", "d")], alg = "plinear-random",
  control = list(maxiter = 10^2))

fm.p <- nls(fo.p, df, start = coef(fm0.p)[c("b", "d")], alg = "plinear")
fm.p
## Nonlinear regression model
##   model: proportion ~ cbind(a = exp(b * time), c = exp(d * time))
##    data: df
##        b        d   .lin.a   .lin.c 
## -0.02066 -0.18194  0.03566  1.00025 
##  residual sum-of-squares: 0.008595
##
## Number of iterations to convergence: 17 
## Achieved convergence tolerance: 5.783e-06
© www.soinside.com 2019 - 2024. All rights reserved.