3

我想为 R 中的以下数据拟合等温线模型。最简单的等温线模型是 Langmuir 模型,此处给出的模型在页面底部给出。下面给出了我的 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)

已编辑

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

4

3 回答 3

3

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

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

接下来,您可以plot(Data)添加一条与您的起始参数相对应的等温线,Qb进行调整b以得出合理的猜测。

下图显示了您的数据集(点)和由with(Data,lines(X,323*0.5*X/(1+0.5*X),col='red'))(红线)生成的 Q = 323 和 b = 0.5 的探针等温线。对我来说,这似乎是一个合理的开始猜测,我试了一下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找到正确的解决方案:

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

在此处输入图像描述

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

在此处输入图像描述

z <- 1/Data
plot(Y~X,z)
abline(lm(Y~X,z))
M <- lm(Y~X,z)

Q <- 1/coef(M)[1]
# 363.2488 

b <- coef(M)[1]/coef(M)[2]
# 0.0741759 

如您所见,两种方法产生的结果基本相同,但线性模型更稳健,不需要起始参数(据我所知,这是实验物理化学中等温线分析的标准方法)。

于 2015-03-06T18:47:45.453 回答
0

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

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

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

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

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

如果要对多组数据进行建模(例如,基于“Sample_name”列,那么 lang.fit 变量将按如下方式计算,这次使用 nlsList 命令:

lang.fit <- nlsList(Y ~ SSmicmen(X,Smax,InvKL) | Sample_name, data=Data)
于 2020-11-28T02:57:12.840 回答
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")

(情节后继续) 截屏

2) mean或者,对 Q 使用 mean(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 如果我们使用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
于 2020-11-28T16:05:14.113 回答