R 收敛误差 对于此数据集:

R 收敛误差 对于此数据集:,r,nls,convergence,R,Nls,Convergence,其中,“x”是温度,而“y”是生物过程的响应变量 我正在尝试适应这个函数 beta.reg<-function(x, Yopt,Tmin,Topt,Tmax, b1) { Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / (Tmax-Topt)) ^ b1 } mod <- nls(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat,

其中,“x”是温度,而“y”是生物过程的响应变量

我正在尝试适应这个函数

beta.reg<-function(x, Yopt,Tmin,Topt,Tmax, b1) {
Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / (Tmax-Topt)) ^ b1
}

mod <- nls(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat,
       start=c(Yopt=6, Tmin=0.1, Topt=24, Tmax=30, b1=1),
       control=nls.control(maxiter=800))

这里有太多的问题,我怀疑它是否能在一篇so文章中得到充分的阐述,但这应该让你开始

首先,看起来您想要
Tmax
,例如<35。这会导致一个问题,因为对于
x
的某些值,
Tmax-x<0
,当您尝试将负数提高到幂次方时(在公式的第二项中),您会得到
NA
。这就是错误消息的原因

其次,非线性模型的收敛性取决于模型公式和数据,因此过程收敛于一组数据而不是另一组数据这一事实完全无关

第三,非线性建模迭代最小化作为参数函数的剩余平方和。如果RSS曲面具有局部极小值,并且您的
开始
非常接近,则算法将找到它。但只有全局最小值才是真正的解决方案。你的问题有很多很多局部极小值

第四,
nls(…)
默认使用高斯-牛顿法。众所周知,高斯-牛顿的参数不稳定(在预测器中加上或减去参数,因此在您的情况下,
Tmin
Tmax
)。幸运的是,
minpak.lm
包实现了Levenberg-Marquardt方法,该方法在这些条件下更加稳定。该包中的
nlsLM(…)
函数使用与
nls(…)
相同的调用顺序,并返回类型为
nls
的and对象,因此该类对象的所有方法也都可以工作。用那个

第五,非线性回归(实际上是所有最小二乘回归)的一个基本假设是残差是正态分布的。因此,您必须使用Q-Q图验证任何解决方案

第六,你的模型有一系列反常的特征。当
Tmin->-Inf
时,模型中的第一项接近
1
。结果表明,这比
Tmin
小于
min(dat$x)
的任何其他值产生的RSS都要低,因此算法都倾向于将
Tmin
驱动到较大的负值。您可以很容易地看到这一点,如下所示:

library(minpack.lm)
mod <- nlsLM(y ~ beta.reg(x, Yopt,Tmin,Topt,Tmax, b1), data=dat,
             start=c(Yopt=6,Tmin=0,Topt=24,Tmax=50, b1=1),
             control=nls.lm.control(maxiter=1024,maxfev=1024))
coef(summary(mod))
#         Estimate   Std. Error     t value     Pr(>|t|)
# Yopt    6.347019    0.2919686 21.73870235 8.055342e-25
# Tmin -155.530098 2204.0011003 -0.07056716 9.440694e-01
# Topt   21.157545    0.6702713 31.56564484 2.240134e-31
# Tmax   35.000000   11.4838614  3.04775537 3.933164e-03
# b1      3.321326    9.1844548  0.36162468 7.194035e-01
sum(residuals(mod)^2)
# [1] 50.24696

par(mfrow=c(1,2))
plot(y~x,dat)
with(as.list(coef(mod)),curve(beta.reg(x, Yopt,Tmin,Topt,Tmax, b1),add=TRUE))
qqnorm(residuals(mod))

从数学上讲,这是一个明显优越的拟合:RSS更低,残差更接近正态分布。同样,参数没有得到很好的估计,也没有物理意义,这是数据(可能还有模型公式)的问题,而不是拟合过程的问题

上述所有情况都表明您的模型有问题。从数学上讲,它的一个问题是,函数在
(Tmin,Tmax)
之外未定义
x
。由于将数据输出到
x=35
,拟合算法将永远不会产生
Tmax<35
(如果收敛)。处理此问题的方法会稍微更改模型函数,使其在该范围外剪裁为0。(不过,根据你问题的物理性质,我不知道这是否合法…)


事实上,网格搜索产生完全相同的结果,与起点无关。请注意,RSS低于早期模型的任何结果,
b1
的估计结果要好得多(与早期模型函数的估计结果非常不同)。残差仍然不正常,但在这种情况下,我想检查数据中是否存在异常值。

为@jlhoward的解决方案添加另一种可能的解决方案

我找到了这个
nls2
包:

library("nls2")
从原始数据集中排除
x~17,35

newdat <- subset(dat, x!=17 & x!=35 )
诊断:

sum(residuals(mod)^2)

# [1] 50.18246
最后,调整后的函数和QQ正常曲线图:

par(mfrow=c(1,2))
with(newdat,plot(y~x,xlim=c(0,35))) 
points(fitted(mod)~I(newdat$x), pch=19)
with(as.list(coef(mod)),
 curve(
  Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / (Tmax-Topt)) ^ b1,
   add=TRUE, col="red"))

qqnorm(residuals(mod))
qqline(residuals(mod))

这是R中的吗?如果是这样,那么你应该添加标签。太棒了@jlhoward!我也认为数据集有很多问题,但这是生物学。。。我会说出你回答的每一点:1-显然,如果我测试温度>30°c,将有大约0的响应。我考虑排除35°C点,以获得
Tmax
;第二,我只举了第二个例子来说明th函数确实有效,并给出了曲线形状的概念;我真的不知道那个包裹,看起来不错!6在未来的实验中,我将包括降低T°C以避免此类错误
Tmin
您的上一个模型似乎具有最好的生物学意义,而不考虑
Tmin
。我认为,使用此模型和数据集很难估计
Tmin
。你认为用x的子集来拟合线性模型来估计Tmin怎么样?这可能是一个解决方案吗?在我这么做之前,我先看看
x~17
周围的数据。这些复制有点奇怪:很难解释为什么你在那里的反应与在
x~10
上的反应相同,加上这些点解释了残差中与正态性的大部分偏差。您可能会考虑排除那些复制和改装。在安装“Min Paul.Lm”包时,我有这个消息错误:[在安装中警告:包:“MyPak.Lm”是不可用的(对于R版本3.1.2)]它是McPACK.LM,带有“C”。对于记录,<代码> NLS2(…)> /代码>(正如您正在使用的)不能最小化RSS,它计算4^5=1024个网格点的每个点的RSS,并报告RSS最低的点。这就是为什么会得到
Tmin=0
Tmin
的值越低,RSS越低,但这是网格中的最低值。这是真的。通过这种方式,我试图将
Tmin
的估计值限制在某种生物学意义上,从而亵渎RSS。这与上一款车型的限制相同吗<代码>beta.regTmax,0,ifelse(xNo。
beta.reg<-function(x, Yopt,Tmin,Topt,Tmax, b1) {
  ifelse(x>Tmax,0,
    ifelse(x<Tmin,0,
      Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / (Tmax-Topt)) ^ b1
  ))
}
coef(summary(mod))
#         Estimate   Std. Error     t value     Pr(>|t|)
# Yopt   6.1470413   0.21976766   27.970636 3.202940e-29
# Tmin -52.8172658 184.16899439   -0.286787 7.756528e-01
# Topt  23.0777898   0.63750721   36.200045 7.638121e-34
# Tmax  30.0039413   0.02529877 1185.984187 1.038918e-98
# b1     0.5966129   0.32439982    1.839128 7.280793e-02

sum(residuals(mod)^2)
# [1] 28.10144

par(mfrow=c(1,2))
plot(y~x,dat)
with(as.list(coef(mod)),curve(beta.reg(x, Yopt,Tmin,Topt,Tmax, b1),add=TRUE))
qqnorm(residuals(mod))
qqline(residuals(mod))
library("nls2")
newdat <- subset(dat, x!=17 & x!=35 )
beta.reg<-with(newdat,  
           y ~ Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / Tmax-Topt))^b1
           )
st1 <- expand.grid(Yopt = seq(4, 8, len = 4),
                   Tmin = seq(0, 4, len = 4), 
                   Topt = seq(15, 25, len = 4),
                   Tmax= seq(28, 38, len = 4),
                   b1 = seq(0, 4, len = 4))
mod <- nls2(beta.reg, start = st1, algorithm = "brute-force")
round(coef(summary(mod)),3)

#     Estimate Std. Error t value Pr(>|t|)
# Yopt    6.667      0.394  16.925    0.000
# Tmin    0.000     12.023   0.000    1.000
# Topt   21.667      0.746  29.032    0.000
# Tmax   31.333      1.924  16.289    0.000
# b1      1.333      1.010   1.320    0.197
sum(residuals(mod)^2)

# [1] 50.18246
par(mfrow=c(1,2))
with(newdat,plot(y~x,xlim=c(0,35))) 
points(fitted(mod)~I(newdat$x), pch=19)
with(as.list(coef(mod)),
 curve(
  Yopt*((x-Tmin)/(Topt-Tmin))^(b1*(Topt-Tmin)/(Tmax-Topt))*((Tmax-x) / (Tmax-Topt)) ^ b1,
   add=TRUE, col="red"))

qqnorm(residuals(mod))
qqline(residuals(mod))