R 收敛误差 对于此数据集:
其中,“x”是温度,而“y”是生物过程的响应变量 我正在尝试适应这个函数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,
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))