R 中 nls() 函数的正确语法
Right syntax for nls() function in R
我是 R 的新手,我正在尝试使用 nls 函数拟合曲线。
我将首先使用 dgamma 函数生成一条曲线 y,然后我想使用 nls 对其进行拟合。
这是我的玩具示例。
´´´
x <- 1:250
y <- dgamma(x,2,0.02)
df <- data.frame(x=x,y=y)
nls(y~ dgamma(x,a,b),data=df,start = list(a =2,b =0.4))
´´´
我得到的错误是
numericDeriv(form[[3L]], names(ind), env) 错误:
评估模型时产生的缺失值或无穷大
另外: 警告信息:
在 dgamma(x, a, b) 中:产生 NaNs
我做错了什么?
谢谢
1) nls 这不是语法错误。该算法不收敛。问题是:
dgamma 产生大 and/or 小数字导致数值不稳定
nls
往往会出现零残差数据的问题,即精确拟合。如果您使用的是 R 4.1,目前是 R 的开发版本,那么添加 nls
参数 control = nls.control(scaleOffset = 1)
可能有助于避免此类问题(参见 https://stat.ethz.ch/R-manual/R-devel/library/stats/html/nls.control.html )。下面我们设法在没有 scaleOffset
的情况下实现收敛,因此它可以在当前版本的 R 上运行。
使用样条拟合创建更多点,例如 1000,然后拟合 log(y) 而不是 y。使用该结果来拟合原始方程,继续使用附加点。
x <- 1:250
y <- dgamma(x, 2, 0.02)
xx <- seq(1, 250, length = 1000)
spl <- spline(x, y, xout = xx)
fo.log <- log(y) ~ dgamma(x, a, b, log = TRUE)
fm.log <- nls(fo.log, data = spl, start = list(a = 2, b = 0.4))
fo <- y ~ dgamma(x, a, b)
fm <- nls(fo, spl, start = coef(fm.log))
fm
给予:
Nonlinear regression model
model: y ~ dgamma(x, a, b)
data: spl
a b
2.00 0.02
residual sum-of-squares: 4.399e-19
Number of iterations to convergence: 1
Achieved convergence tolerance: 7.806e-08
2) optim optim
通常适用于非线性最小二乘问题。有了它,我们就可以直接得到一个合适的,而无需上面的变通方法。生成的警告在达到收敛时可以忽略(输出中的convergence = 0
)。
rss <- function(p, x, y) sum((y - dgamma(x, p[["a"]], p[["b"]]))^2)
optim(c(a = 2, b = 0.4), rss, x = x, y = y)
给予:
$par
a b
1.9974423 0.0199842
$value
[1] 5.209388e-09
$counts
function gradient
61 NA
$convergence
[1] 0
$message
NULL
我是 R 的新手,我正在尝试使用 nls 函数拟合曲线。 我将首先使用 dgamma 函数生成一条曲线 y,然后我想使用 nls 对其进行拟合。 这是我的玩具示例。
´´´
x <- 1:250
y <- dgamma(x,2,0.02)
df <- data.frame(x=x,y=y)
nls(y~ dgamma(x,a,b),data=df,start = list(a =2,b =0.4))
´´´
我得到的错误是
numericDeriv(form[[3L]], names(ind), env) 错误: 评估模型时产生的缺失值或无穷大 另外: 警告信息: 在 dgamma(x, a, b) 中:产生 NaNs
我做错了什么?
谢谢
1) nls 这不是语法错误。该算法不收敛。问题是:
dgamma 产生大 and/or 小数字导致数值不稳定
nls
往往会出现零残差数据的问题,即精确拟合。如果您使用的是 R 4.1,目前是 R 的开发版本,那么添加nls
参数control = nls.control(scaleOffset = 1)
可能有助于避免此类问题(参见 https://stat.ethz.ch/R-manual/R-devel/library/stats/html/nls.control.html )。下面我们设法在没有scaleOffset
的情况下实现收敛,因此它可以在当前版本的 R 上运行。
使用样条拟合创建更多点,例如 1000,然后拟合 log(y) 而不是 y。使用该结果来拟合原始方程,继续使用附加点。
x <- 1:250
y <- dgamma(x, 2, 0.02)
xx <- seq(1, 250, length = 1000)
spl <- spline(x, y, xout = xx)
fo.log <- log(y) ~ dgamma(x, a, b, log = TRUE)
fm.log <- nls(fo.log, data = spl, start = list(a = 2, b = 0.4))
fo <- y ~ dgamma(x, a, b)
fm <- nls(fo, spl, start = coef(fm.log))
fm
给予:
Nonlinear regression model
model: y ~ dgamma(x, a, b)
data: spl
a b
2.00 0.02
residual sum-of-squares: 4.399e-19
Number of iterations to convergence: 1
Achieved convergence tolerance: 7.806e-08
2) optim optim
通常适用于非线性最小二乘问题。有了它,我们就可以直接得到一个合适的,而无需上面的变通方法。生成的警告在达到收敛时可以忽略(输出中的convergence = 0
)。
rss <- function(p, x, y) sum((y - dgamma(x, p[["a"]], p[["b"]]))^2)
optim(c(a = 2, b = 0.4), rss, x = x, y = y)
给予:
$par
a b
1.9974423 0.0199842
$value
[1] 5.209388e-09
$counts
function gradient
61 NA
$convergence
[1] 0
$message
NULL