使用 nls 将曲线拟合到 R 中的威布尔分布
Fitting a curve to weibull distribution in R using nls
我正在尝试将此数据拟合为 weibull 分布:
我的 x
和 y
变量是:
y <- c(1, 1, 1, 4, 7, 20, 7, 14, 19, 15, 18, 3, 4, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1)
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)
剧情是这样的:
我正在寻找这样的东西:
fitted plot
我想用威布尔曲线拟合它。我像这样在 R 中使用 nls 函数:
nls(y ~ ((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)))
这个函数总是抛出一个错误说:
Error in numericDeriv(form[[3L]], names(ind), env) :
Missing value or an infinity produced when evaluating the model
In addition: Warning message:
In nls(y ~ ((a/b) * ((x/b)^(a - 1)) * exp(-(x/b)^a))) :
No starting values specified for some parameters.
Initializing ‘a’, ‘b’ to '1.'.
Consider specifying 'start' or using a selfStart model
所以首先我尝试了不同的起始值但没有成功。我无法理解如何对起始值进行 "good" 猜测。
然后我使用 SSweibull(x, Asym, Drop, lrc, pwr)
函数,它是一个 selfStart 函数。现在 SSWeibull 函数需要 Asym、Drop、lrc 和 pwr 的值,而我不知道这些值可能是什么。
如果有人能帮助我弄清楚如何进行,我将不胜感激。
数据背景:我从 bugzilla 中获取了一些数据,我的 "y" 变量是特定月份报告的错误数量,"x" 变量是发布后的月份数。
您可以考虑修改公式以更好地拟合数据。例如,您可以添加一个截距(因为您的数据在 1 而不是 0,这是模型想要做的)和一个标量乘数,因为您实际上并不适合密度。
花一些时间真正思考哪些参数有意义总是值得的,因为模型拟合过程通常对初始估计非常敏感。您还可以进行网格搜索,在其中提出可能的参数范围,并尝试使用错误捕获功能将模型与各种组合相匹配。 nls2
有一个选项可以为您执行此操作。
因此,例如,
## Put the data in a data.frame
dat <- data.frame(x=x, y=y)
## Try some possible parameter combinations
library(nls2)
pars <- expand.grid(a=seq(0.1, 100, len=10),
b=seq(0.1, 100, len=10),
c=1,
d=seq(10, 100, len=10))
## brute-force them
## note the model has changed slightly
res <- nls2(y ~ d*((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)) + c, data=dat,
start=pars, algorithm='brute-force')
## use the results with another algorithm
res1 <- nls(y ~ d*((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)) + c, data=dat,
start=as.list(coef(res)))
## See how it looks
plot(dat, col="steelblue", pch=16)
points(dat$x, predict(res), col="salmon", type="l", lwd=2)
不完美,但这是一个开始。
我正在尝试将此数据拟合为 weibull 分布:
我的 x
和 y
变量是:
y <- c(1, 1, 1, 4, 7, 20, 7, 14, 19, 15, 18, 3, 4, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1)
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24)
剧情是这样的:
我正在寻找这样的东西: fitted plot
我想用威布尔曲线拟合它。我像这样在 R 中使用 nls 函数:
nls(y ~ ((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)))
这个函数总是抛出一个错误说:
Error in numericDeriv(form[[3L]], names(ind), env) :
Missing value or an infinity produced when evaluating the model
In addition: Warning message:
In nls(y ~ ((a/b) * ((x/b)^(a - 1)) * exp(-(x/b)^a))) :
No starting values specified for some parameters.
Initializing ‘a’, ‘b’ to '1.'.
Consider specifying 'start' or using a selfStart model
所以首先我尝试了不同的起始值但没有成功。我无法理解如何对起始值进行 "good" 猜测。
然后我使用 SSweibull(x, Asym, Drop, lrc, pwr)
函数,它是一个 selfStart 函数。现在 SSWeibull 函数需要 Asym、Drop、lrc 和 pwr 的值,而我不知道这些值可能是什么。
如果有人能帮助我弄清楚如何进行,我将不胜感激。
数据背景:我从 bugzilla 中获取了一些数据,我的 "y" 变量是特定月份报告的错误数量,"x" 变量是发布后的月份数。
您可以考虑修改公式以更好地拟合数据。例如,您可以添加一个截距(因为您的数据在 1 而不是 0,这是模型想要做的)和一个标量乘数,因为您实际上并不适合密度。
花一些时间真正思考哪些参数有意义总是值得的,因为模型拟合过程通常对初始估计非常敏感。您还可以进行网格搜索,在其中提出可能的参数范围,并尝试使用错误捕获功能将模型与各种组合相匹配。 nls2
有一个选项可以为您执行此操作。
因此,例如,
## Put the data in a data.frame
dat <- data.frame(x=x, y=y)
## Try some possible parameter combinations
library(nls2)
pars <- expand.grid(a=seq(0.1, 100, len=10),
b=seq(0.1, 100, len=10),
c=1,
d=seq(10, 100, len=10))
## brute-force them
## note the model has changed slightly
res <- nls2(y ~ d*((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)) + c, data=dat,
start=pars, algorithm='brute-force')
## use the results with another algorithm
res1 <- nls(y ~ d*((a/b) * ((x/b)^(a-1)) * exp(- (x/b)^a)) + c, data=dat,
start=as.list(coef(res)))
## See how it looks
plot(dat, col="steelblue", pch=16)
points(dat$x, predict(res), col="salmon", type="l", lwd=2)
不完美,但这是一个开始。