为什么nls()给我“初始参数估计时的奇异梯度矩阵”错误?


21

我有一些有关减排和每辆车成本的基本数据:

q24 <- read.table(text = "reductions  cost.per.car
    50  45
    55  55
    60  62
    65  70
    70  80
    75  90
    80  100
    85  200
    90  375
    95  600
    ",header = TRUE, sep = "")

我知道这是一个指数函数,因此我希望能够找到适合的模型:

    model <- nls(cost.per.car ~ a * exp(b * reductions) + c, 
         data = q24, 
         start = list(a=1, b=1, c=0))

但出现错误:

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

我已经阅读了很多有关所见错误的问题,并且正在收集有关问题的可能是我需要更好/不同的start值(这initial parameter estimates更有意义),但由于不确定,我不确定我拥有的数据,如何估算更好的参数。


我建议您通过在我们的网站上搜索错误消息来开始解密。
ub

3
实际上,我是这样做的,而我对全部错误的搜索都出现了一个带有三个数据点且没有答案的半熟问题。但是,您的更具体的搜索确实会得到一些结果。可能是因为您在这里有更多的经验,并且知道哪些术语是相关的。
阿曼达

我发现的有关软件错误的一件事是,搜索特定的错误消息(通常用引号引起来)是确定它是否曾经被讨论过的最可靠方法。(这不仅适用于SE网站,而且适用于整个Internet。)正如我们的“保留”消息所述,如果您进行的其他研究无法解决您的问题,那么请您再回来稍加推销:这个问题在统计与计算的交叉点,并可能在这里暴露出一些有趣的问题。
ub

1
起始值的拟合值与数据相差很远;exp(50)exp(95)x = 50和x = 95的y值进行比较。如果设置c=0并取y的对数(建立线性关系),则可以使用回归获得足以满足数据需求的log()和初始估计值(或者如果通过原点拟合一条线,则可以离开在1处,仅使用的估算值;这也足以满足您的数据)。如果在这两个值之间的相当窄的区间之外,您将遇到一些问题。[或者尝试使用其他算法]b a b b一种b一种bb
Glen_b-恢复莫妮卡2015年

1
谢谢@Glen_b。我希望我可以使用R代替图形计算器来浏览统计入门的教科书(并跳过课程本身),所以我仅从最简单的统计见解开始,但是有很多在R中进行其他切片和切块的经验。
阿曼达

Answers:


38

自动寻找非线性模型的良好起始值是一门艺术。(对于一次性数据集,只需绘制数据并直观地进行一些猜测就相对容易。)一种方法是线性化模型并使用最小二乘估计。

在这种情况下,模型具有以下形式

Ëÿ=一种经验值bX+C

对于未知参数。指数的存在鼓励我们使用对数-但是的加法很难做到这一点。但是请注意,如果a为正,则c将小于Y的最小期望值-因此可能会小于Y的最小观察值。(如果a可能为负,则还必须考虑c的值,该c值比Y的最大观察值大一点。)c一种bCC一种Cÿÿ一种Cÿ

然后,让我们通过使用c 0作为初始估计c 0来照顾,大约是观测值y i的最小值的一半。现在可以在没有那个棘手的加法项的情况下重写模型,因为CC0ÿ一世

Ëÿ-C0一种经验值bX

我们可以采取的日志:

日志Ëÿ-C0日志一种+bX

那是对模型的线性近似。两个b可以用最小二乘估计。日志一种b

这是修改后的代码:

c.0 <- min(q24$cost.per.car) * 0.5
model.0 <- lm(log(cost.per.car - c.0) ~ reductions, data=q24)
start <- list(a=exp(coef(model.0)[1]), b=coef(model.0)[2], c=c.0)
model <- nls(cost.per.car ~ a * exp(b * reductions) + c, data = q24, start = start)

其输出(用于示例数据)为

Nonlinear regression model
  model: cost.per.car ~ a * exp(b * reductions) + c
   data: q24
        a         b         c 
 0.003289  0.126805 48.487386 
 residual sum-of-squares: 2243

Number of iterations to convergence: 38 
Achieved convergence tolerance: 1.374e-06

收敛看起来不错。让我们来画一下:

plot(q24)
p <- coef(model)
curve(p["a"] * exp(p["b"] * x) + p["c"], lwd=2, col="Red", add=TRUE)

数字

运行良好!

自动执行此操作时,您可以对残差进行一些快速分析,例如将其极端值与()数据中的分布进行比较。您可能还需要类似的代码来处理a < 0的可能性;我将其保留为练习。ÿ一种<0


估计初始值的另一种方法依赖于理解它们的含义,这可以基于经验,物理理论 。我的答案描述了(中等难度)非线性拟合的扩展示例,其初始值可以通过这种方式确定在/stats//a/15769

/stats//a/32832上描述和说明了散点图的可视化分析(以确定初始参数估计值)。

在某些情况下,会产生一系列非线性拟合,在这些序列中,您可以期望解的变化缓慢。在这种情况下,将先前的解决方案用作下一个解决方案的初始估计通常很方便(且快速)。我记得在/stats//a/63169使用这种技术(无评论)。


2

该库能够解决我的nls问题singular gradienthttp : //www.r-bloggers.com/a-better-nls/ 示例:

library(minpack.lm)
nlsLM(function, start=list(variable=2,variable2=12))

该函数nls.lm现在似乎已被调用。
马特

-1

所以...我想我误将其理解为指数函数。我只需要poly()

model <- lm(cost.per.car ~ poly(reductions, 3), data=q24)
new.data <- data.frame(reductions = c(91,92,93,94))
predict(model, new.data)

plot(q24)
lines(q24$reductions, predict(model, list(reductions = q24$reductions)))

或者,使用lattice

xyplot(cost.per.car ~ reductions, data = q24,
       panel = function(x, y) {
         panel.xyplot(x, y)
         panel.lines(x, predict(model,list(reductions = x) ))
       }, 
       xlab = "Reductions", 
       ylab = "Cost per car")

2
这不能回答您提出的问题,而是将其更改为其他内容(而不是有趣的IMHO)。
ub

6
尽管它可以解决拟合函数来表示数据的问题,但是您接受的答案并不是您对问题的期望。@whuber先生为您提供了出色的解释,值得您接受。
Lourenco
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.