拟合R中的非线性Langmuir等温线

时间:2015-03-06 16:31:49

标签: r nonlinear-functions nls non-linear-regression

我想在R中使用等温模型得到以下数据。最简单的等温模型是Langmuir模型,这里给出model is given in the bottom of the page。我的MWE在下面给出了抛出错误。我想知道Isotherm模型是否有任何R包。

X <- c(10, 30, 50, 70, 100, 125)
Y <- c(155, 250, 270, 330, 320, 323)
Data <- data.frame(X, Y)
LangIMfm2 <- nls(formula = Y ~ Q*b*X/(1+b*X),  data = Data, start = list(Q = 1, b = 0.5), algorith = "port")

Error in nls(formula = Y ~ Q * b * X/(1 + b * X), data = Data, start = list(Q = 1,  : 
  Convergence failure: singular convergence (7)

被修改

一些非线性模型可以转换为线性模型。我的理解是,非线性模型的估计与其线性模型形式之间可能存在一对一的关系,但它们相应的标准误差彼此无关。这个断言是真的吗?通过转换为线性来拟合非线性模型是否存在任何缺陷?

3 个答案:

答案 0 :(得分:3)

我不知道这样的软件包,我个人认为你不需要一个,因为问题可以通过基础R来解决。

nls对起始参数很敏感,所以你应该从良好的开始猜测开始。您可以轻松评估Q,因为它对应于x - > Inf的等温线的渐近极限,因此从Q=323开始是合理的(这是{{1}的最后一个值在您的示例数据集中)。

接下来,您可以执行Y并添加一行,其中包含与您的起始参数plot(Data)Q以及调整b相对应的等温线,以便找到合理的猜测。

下图显示了您的数据集(点)和探针等温线,Q = 323和b = 0.5,由b(红线)生成。对我来说这似乎是一个合理的开始猜测,我尝试了with(Data,lines(X,323*0.5*X/(1+0.5*X),col='red'))

nls

并绘制预测线以确保LangIMfm2 <- nls(formula = Y ~ Q*b*X/(1+b*X), data = Data, start = list(Q = 300, b = 1), algorith = "port") # Nonlinear regression model # model: Y ~ Q * b * X/(1 + b * X) # data: Data # Q b # 366.2778 0.0721 # residual sum-of-squares: 920.6 # # Algorithm "port", convergence message: relative convergence (4) 找到正确的解决方案:

nls

enter image description here

话虽如此,我建议使用更有效的策略,基于模型的线性化,通过在倒数坐标中重写等温线方程:

enter image description here

lines(Data$X,predict(LangIMfm2),col='green')

正如您所看到的,两种方法产生的结果基本相同,但线性模型更稳健,不需要启动参数(据我记得,它是等温线分析的标准方法。实验物理化学。)

答案 1 :(得分:0)

您可以在nlme软件包中为R使用SSmicmen自启动函数(请参阅Ritz和Streibig,2008,带有R的非线性回归),该函数根据Michaelis-Menten(MM)的线性化形式的拟合来计算初始参数)方程式。幸运的是,MM方程具有可用于Langmuir方程的形式S = Smax * x /(KL + x)。我发现nlshelper和tidyverse软件包可用于对nls命令的结果进行建模并将其导出到表和图中,特别是在对样本组进行建模时。这是我的用于模拟一组吸附数据的代码:

{
    Hello: [[2001, 51], [2003, 52], [2002, 90]]
    Jello: [[2009, 22], [2003, 4], [2002, 11]]
    Cello: [[2001, 16]]
}
library(tidyverse)
library(nlme)
library(nlshelper)

为简单起见,此处将Langmuir亲和常数建模为1 / KL。应用此代码,我得到的参数估计与上面给出的@Marat相同。

下面的简单代码允许对数据进行整理,以创建一个包含原始点和拟合线的ggplot对象(即geom_point代表原始X和Y数据,geom_line代表原始X和YHat)。

lang.fit <- nls(Y ~ SSmicmen(X,Smax,InvKL), data=Data)
fit.summary <- tidy(lang.fit)
fit.coefs <- coef(lang.fit)

如果要建模多组数据(例如,基于“ Sample_name”列,则将使用nlsList命令,如下所示计算lang.fit变量:

FitY <- tibble(predict(lang.fit))
YHat <- FitY[,1]
Data2 <- cbind(Data, YHat)

答案 2 :(得分:0)

问题是起始值。我们展示了两种解决方法,以及使用问题中的起始值也可以收敛的另一种方法。

1)plinear 右手边在Q * b中是线性的,因此最好将b吸收到Q中,然后我们有一个线性输入的参数,因此更容易求解。同样,对于plinear算法,线性参数不需要起始值,因此仅需要指定b的起始值。对于plinear,应将nls公式的右侧指定为与线性参数相乘的向量。运行nls在下面给出fm0的结果将是名为b.lin的系数,其中Q = .lin / b。

我们已经从fm0得到了答案,但是如果我们希望以bQ而不是b.lin的方式进行清洁测试,我们可以如图所示,使用fm0返回的系数所隐含的起始值来运行问题中的原始公式。

fm0 <- nls(Y ~ X/(1+b*X), Data, start = list(b = 0.5), alg = "plinear")

st <- with(as.list(coef(fm0)), list(b = b, Q = .lin/b))
fm <- nls(Y ~ Q*b*X/(1+b*X), Data, start = st)
fm

给予

Nonlinear regression model
  model: Y ~ Q * b * X/(1 + b * X)
   data: Data
       b        Q 
  0.0721 366.2778 
 residual sum-of-squares: 920.6

Number of iterations to convergence: 0 
Achieved convergence tolerance: 9.611e-07

我们可以显示结果。点是数据,红线是拟合曲线。

plot(Data)
lines(fitted(fm) ~ X, Data, col = "red")

(情节后继续) screenshot

2)均值或者,对于Q使用均值(Data $ Y)的起始值似乎效果很好。

nls(Y ~ Q*b*X/(1+b*X), Data, start = list(b = 0.5, Q = mean(Data$Y)))

给予:

Nonlinear regression model
  model: Y ~ Q * b * X/(1 + b * X)
   data: Data
       b        Q 
  0.0721 366.2779 
 residual sum-of-squares: 920.6

Number of iterations to convergence: 6 
Achieved convergence tolerance: 5.818e-06

该问题对于我们使用的b已经具有一个合理的起始值,但是如果需要,可以将Y设置为Q*b以便将其取消,将X设置为均值(Data $ X)并求解b以给出b = 1 - 1/mean(Data$X)作为可能的起始值。尽管未显示使用b的起始值和mean(Data$Y)作为Q的起始值,也会导致收敛。

3)优化如果我们使用optim,则算法甚至会收敛于问题中使用的初始值。我们形成残差平方和并将其最小化:

rss <- function(p) {
  Q <- p[1]
  b <- p[2]
  with(Data, sum((Y - b*Q*X/(1+b*X))^2))
}
optim(c(1, 0.5), rss)

给予:

$par
[1] 366.27028219   0.07213613

$value
[1] 920.62

$counts
function gradient 
     249       NA 

$convergence
[1] 0

$message
NULL