使用 R 的 nls() 进行变化点分析

机器算法验证 r 回归 变化点 nls
2022-01-25 23:12:43

我正在尝试使用nls()R实现“变化点”分析或多相回归。

这是我制作的一些假数据我想用来拟合数据的公式是:

y=β0+β1x+β2max(0,xδ)

这应该做的是将数据拟合到具有一定截距和斜率()的某个点,然后,在某个 x 值()之后,将斜率增加这就是整个 max 的意义所在。点之前,它将等于 0,并且将被清零。β0β1δβ2δβ2

所以,这是我的功能:

changePoint <- function(x, b0, slope1, slope2, delta){ 
   b0 + (x*slope1) + (max(0, x-delta) * slope2)
}

我尝试以这种方式拟合模型

nls(y ~ changePoint(x, b0, slope1, slope2, delta), 
    data = data, 
    start = c(b0 = 50, slope1 = 0, slope2 = 2, delta = 48))

我选择了那些起始参数,因为我知道那些是起始参数,因为我做了数据。

但是,我收到此错误:

Error in nlsModel(formula, mf, start, wts) : 
  singular gradient matrix at initial parameter estimates

我刚刚制作了不幸的数据吗?我首先尝试在真实数据上进行拟合,并得到同样的错误,我只是认为我的初始启动参数不够好。

2个回答

(起初我认为这可能是由于max未矢量化而导致的问题,但事实并非如此。使用 changePoint确实很痛苦,因此进行了以下修改:

changePoint <- function(x, b0, slope1, slope2, delta) { 
   b0 + (x*slope1) + (sapply(x-delta, function (t) max(0, t)) * slope2)
}

此 R-help 邮件列表帖子描述了可能导致此错误的一种方式:公式的 rhs 被过度参数化,因此同时更改两个参数可以使数据具有相同的拟合度。我看不出你的模型是怎样的,但也许是这样。

在任何情况下,您都可以编写自己的目标函数并将其最小化。下面的函数给出了数据点 (x,y) 的平方误差和参数的某个值(函数的奇怪参数结构是为了说明如何optim工作):

sqerror <- function (par, x, y) {
  sum((y - changePoint(x, par[1], par[2], par[3], par[4]))^2)
}

然后我们说:

optim(par = c(50, 0, 2, 48), fn = sqerror, x = x, y = data)

并看到:

$par
[1] 54.53436800 -0.09283594  2.07356459 48.00000006

请注意,对于我的假数据 ( x <- 40:60; data <- changePoint(x, 50, 0, 2, 48) + rnorm(21, 0, 0.5)),有很多局部最大值取决于您给出的初始参数值。我想如果您想认真对待这一点,您会使用随机初始参数多次调用优化器并检查结果的分布。

只是想补充一点,您可以使用许多其他软件包来做到这一点。如果您想估计更改点周围的不确定性(nls 无法做到),请尝试该mcp软件包。

# Simulate the data
df = data.frame(x = 1:100)
df$y = c(rnorm(20, 50, 5), rnorm(80, 50 + 1.5*(df$x[21:100] - 20), 5))

# Fit the model
model = list(
  y ~ 1,  # Intercept
  ~ 0 + x  # Joined slope
)
library(mcp)
fit = mcp(model, df)

让我们用预测间隔(绿线)绘制它。蓝色密度是变化点位置的后验分布:

# Plot it
plot(fit, q_predict = T)

plot_pars(fit)您可以使用和更详细地检查各个参数summary(fit)

在此处输入图像描述