R语言 nls模型中的奇异梯度-我怎样才能让它工作?

643ylb08  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(739)

我有一些数据,我想在这些数据上拟合一个非线性回归模型。这个模型是一个物理模型,用来计算氯化物扩散系数。在我的例子中,这个模型看起来像
Cx = Ci +(铯- Ci)* erfc(x /(平方(4 * D * t))
其中Ci = 0.020664,t = 28/365,x和Cx在数据中,Cs和D是要计算的系数,Erfc是互补误差函数。
我有一些数据

data = data.frame(x=c(2.13, 4.38, 6.38, 8.13, 10.38, 13.88, 17.38), 
                  Cx=c(0.085, 0.017, 0.011, 0.010, 0.009, 0.010, 0.009))

所以我用R写的是

erf <- function(x) 2 * pnorm(x * sqrt(2)) - 1 # error function
erfc <- function(x) 1 - erf(x) # complementary error function

m1 <- nls(formula = Cx ~ 0.020664 + (Cs - 0.020664) *
            erfc(x / (sqrt(4 * D * (28/365)))), 
          data = data,
          start = list(Cs = 0.5, D = 50))

这给了我一个错误信息“奇异梯度”,因为数据已经给出了,我也不能改变模型,有人知道如何解决这个问题吗?
(我经常看到,当这个错误发生时,建议使用与nls不同的库,但是这些库(即nlsr)不能派生erfc函数。)

bnl4lu3b

bnl4lu3b1#

由于erfc〉0,如果Cs - 0.020664为正,则第二项为正,因此整个RHS将高于0.020664,而除第一项外的所有点都低于0.020664;同样,如果Cs - 0.020664为负,则所有点都低于0.020664,在这种情况下,它将远离第一点。
因此,这不是寻找不同算法的问题--您的模型只是不适合数据。
同样作为一个一般性的评论,当nls失败时简单地寻找一个不同的算法通常是一个糟糕的策略,因为我们这里的情况经常是这样的,一个更好的策略是更好地理解模型并改进它。
如果我们将模型稍微修改为1和erfc的线性组合,则可以获得良好的拟合。线性组合系数为. lin. A和.lin.B,使用多线性算法时不需要初始值。该算法仅在3次迭代中收敛,与下图一起显示它与数据拟合良好。请注意,此修订模型仍具有参数D,因此如果这是您感兴趣的主要参数,您仍可以使用此模型。
在下图中,圆圈是数据点,直线是数据点处的拟合值。

fm <- nls(formula = Cx ~ cbind(A = 1, B = erfc(x / sqrt(4 * D * 28/365))), 
      data = data, start = list(D = 25), algorithm = "plinear")

fm
## Nonlinear regression model
##   model: Cx ~ cbind(A = 1, B = erfc(x/sqrt(4 * D * 28/365)))
##    data: data
##         D    .lin.A    .lin.B 
## 25.932426  0.009704  0.263631 
##  residual sum-of-squares: 2.041e-06
##
## Number of iterations to convergence: 3 
## Achieved convergence tolerance: 6.247e-06

plot(Cx ~ x, data)
lines(fitted(fm) ~ x, data)

相关问题