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


16

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

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

ÿ=β0+β1个X+β2最大值0X-δ

这应该做的是使数据具有特定的截距和斜率(β0β1个),直到特定点,然后在某个x值(δ)之后,将斜率增加β2。这就是整个最大事情。在δ点之前,它等于0,并且β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

我刚刚做了不幸的数据吗?我首先尝试将其拟合到实际数据上,并得到相同的错误,但我只是发现我的初始启动参数不够好。

Answers:


12

(起初,我认为这可能是由于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)),有很多局部最大值,具体取决于您提供的初始参数值。我想如果您想认真对待这一点,可以使用随机的初始参数多次调用优化器,并检查结果的分布。


Bill Venables的这篇文章很好地解释了这种分析涉及的问题。
亚伦

6
除了在您的第一个代码段中(麻烦的)sapply调用之外,您始终可以使用pmax
主教

0

只是想补充一点,您可以使用许多其他软件包来执行此操作。如果要估计更改点周围的不确定性(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)

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.