将曲线拟合到特定数据 [英] Fitting a curve to specific data

查看:114
本文介绍了将曲线拟合到特定数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的论文中包含以下数据:

  28 45 
91 14
102 11
393 5
4492 1.77

我需要对此进行拟合。如果我绘制它,那么这就是我得到的。





我认为某种指数曲线应该适合此数据。我正在使用GNUplot。有人可以告诉我哪种曲线适合该曲线以及可以使用哪些初始参数吗?

解决方案

以防万一 R 是一个选项,下面是您可能使用的两种方法的示意图。



第一种方法:评估一组候选模型的拟合优度

这可能是最好的方法,因为它利用了您可能已经知道或期望的变量之间的关系。

 #读入数据
dat<-read.table(text = xy
28 45
91 14
102 11
393 5
4492 1.77,标头= TRUE)

#快速目测
图(dat ); lines(dat)

 #可能的模型有很多……只是在弥补
#需要付出更多的努力,应该增加一些更好的候选者。
#可能的模型种类繁多...
模型<-list(lm(y〜x,data = dat),
lm(y〜I(1 / x),数据= dat),
lm(y〜log(x),数据= dat),
nls(y〜I(1 / / x * a)+ b * x,data = dat,start = list(a = 1,b = 1)),
nls(y〜(a + b * log(x)),data = dat, start = setNames(coef(lm(y〜log(x),data = dat)),c( a, b)))),
nls(y〜I(exp(1)^( a + b * x)),data = dat,start = list(a = 0,b = 0)),
nls(y〜I(1 / x * a)+ b,data = dat,start = list(a = 1,b = 1))


#快速查看这些模型的视觉拟合
库(ggplot2)
ggplot (dat,aes(x,y))+ geom_point(大小= 5)+
stat_smooth(方法= lm,公式= as.formula(models [[1]]),大小= 1,se =假,颜色=黑色)+
stat_smooth(方法= lm,公式= as.formula(models [[2]]),大小= 1,se =假,颜色= blue)+
stat_smooth(方法= lm,公式= as.formula(模型[ [3]]),大小= 1,se =否,颜色=黄色)+
stat_smooth(方法= nls,公式= as.formula(models [[4]]),数据= dat,方法.args = list(开始= list(a = 0,b = 0)),大小= 1,se = FALSE,颜色= red,线型= 2)+
stat_smooth(method = nls,公式= as.formula(models [[5]]),data = dat,method.args = list(start = setNames(coef(lm(y〜log(x),data = dat))),c( a, b))),大小= 1,se =否,颜色=绿色,线型= 2)+
stat_smooth(方法= nls,公式= as.formula(models [[6]]),数据= dat,method.args = list(start = list(a = 0,b = 0)),大小= 1,se = FALSE,color = violet)+
stat_smooth(方法= nls,公式= as.formula(models [[7]]),data = dat,m ethod.args = list(start = list(a = 0,b = 0)),大小= 1,se = FALSE,color = orange,线型= 2)



橙色曲线看起来不错。让我们看看当我们测量这些模型的相对优度时,它的排名是...

 #计算AIC和AICc (对于小样本)对于每个
#模型,以查看哪种模型最好,即具有最低的AIC
库(AICcmodavg);库(plyr); library(stringr)
ldply(models,function(mod){data.frame(AICc = AICc(mod),AIC = AIC(mod),model = deparse(formula(mod)))})

AICc AIC模型
1 70.23024 46.23024 y〜x
2 44.37075 20.37075 y〜I(1 / x)
3 67.00075 43.00075 y〜log(x)
4 43.82083 19.82083 y〜I(1 / x * a)+ b * x
5 67.00075 43.00075 y〜(a + b * log(x))
6 52.75748 28.75748 y〜I(exp(1 )^(a + b * x))
7 44.37075 20.37075 y〜I(1 / x * a)+ b

#y〜I(1 / x * a)+ b * x是在此曲线中尝试过的最佳模型
#它非常适合该图并且具有拟合统计量的最佳优势
#毫无疑问,对nls的理解更好,数据也更好可以找到合适的
#函数。也许这里的优化方法可能是
#有用的:http://stats.stackexchange.com/a/21098/7744



第二种方法:使用遗传编程来搜索大量模型



这似乎是一种黑暗的方法进行曲线拟合。您不必在开始时指定太多,尽管也许我做错了...

 #符号回归使用遗传编程
#http://rsymbolic.org/projects/rgp/wiki/Symbolic_Regression
库(rgp)
#这可能会花费一些时间并抛出
#a很多警告...
result1<-symbolicRegression(y〜x,
data = dat,functionSet = mathFunctionSet,
stopCondition = makeStepsStopCondition(2000)
#检查结果,它们每次都会不同...
(symbreg< -result1 $ population [[which.min(sapply(result1 $ population,result1 $ fitnessFunction))]])

函数(x)
tan((x-x + tan(x))* x)
#非常奇怪...

#检查外观是否合适
ggplot()+ geom_point(data = dat,aes(x,y),size = 3)+
geom_line(data = data.frame(symbx = dat $ x,symby = sapply(dat $ x,symbreg) ),aes(symbx,symby),颜色=红色)



实际上是非常差的视觉效果。也许需要更多的努力才能从基因编程中获得高质量的结果...



信用:曲线拟合答案1 ,通过曲线拟合答案2 /stackoverflow.com/users/516548/g-grothendieck\">G。格洛腾迪克。


I have the following data in my thesis:

28 45
91 14
102 11
393 5
4492 1.77

I need to fit a curve into this. If I plot it, then this is what I get.

I think some kind of exponential curve should fit this data. I am using GNUplot. Can someone tell me what kind of curve will fit this and what initial parameters I can use?

解决方案

Just in case R is an option, here's a sketch of two methods you might use.

First method: evaluate the goodness of fit of a set of candidate models

This is probably the best way as it takes advantage of what you might already know or expect about the relationship between the variables.

# read in the data
dat <- read.table(text= "x y 
28 45
91 14
102 11
393 5
4492 1.77", header = TRUE)

# quick visual inspection
plot(dat); lines(dat)

# a smattering of possible models... just made up on the spot
# with more effort some better candidates should be added
# a smattering of possible models...
models <- list(lm(y ~ x, data = dat), 
               lm(y ~ I(1 / x), data = dat),
               lm(y ~ log(x), data = dat),
               nls(y ~ I(1 / x * a) + b * x, data = dat, start = list(a = 1, b = 1)), 
               nls(y ~ (a + b * log(x)), data = dat, start = setNames(coef(lm(y ~ log(x), data = dat)), c("a", "b"))),
               nls(y ~ I(exp(1) ^ (a + b * x)), data = dat, start = list(a = 0,b = 0)),
               nls(y ~ I(1 / x * a) + b, data = dat, start = list(a = 1,b = 1))
)

# have a quick look at the visual fit of these models
library(ggplot2)
ggplot(dat, aes(x, y)) + geom_point(size = 5) +
    stat_smooth(method = lm, formula = as.formula(models[[1]]), size = 1, se = FALSE, color = "black") + 
    stat_smooth(method = lm, formula = as.formula(models[[2]]), size = 1, se = FALSE, color = "blue") + 
    stat_smooth(method = lm, formula = as.formula(models[[3]]), size = 1, se = FALSE, color = "yellow") + 
    stat_smooth(method = nls, formula = as.formula(models[[4]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "red", linetype = 2) + 
    stat_smooth(method = nls, formula = as.formula(models[[5]]), data = dat, method.args = list(start = setNames(coef(lm(y ~ log(x), data = dat)), c("a", "b"))), size = 1, se = FALSE, color = "green", linetype = 2) +
    stat_smooth(method = nls, formula = as.formula(models[[6]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "violet") +
    stat_smooth(method = nls, formula = as.formula(models[[7]]), data = dat, method.args = list(start = list(a = 0,b = 0)), size = 1, se = FALSE, color = "orange", linetype = 2)

The orange curve looks pretty good. Let's see how it ranks when we measure the relative goodness of fit of these models are...

# calculate the AIC and AICc (for small samples) for each 
# model to see which one is best, ie has the lowest AIC
library(AICcmodavg); library(plyr); library(stringr)
ldply(models, function(mod){ data.frame(AICc = AICc(mod), AIC = AIC(mod), model = deparse(formula(mod))) })

      AICc      AIC                     model
1 70.23024 46.23024                     y ~ x
2 44.37075 20.37075                y ~ I(1/x)
3 67.00075 43.00075                y ~ log(x)
4 43.82083 19.82083    y ~ I(1/x * a) + b * x
5 67.00075 43.00075      y ~ (a + b * log(x))
6 52.75748 28.75748 y ~ I(exp(1)^(a + b * x))
7 44.37075 20.37075        y ~ I(1/x * a) + b

# y ~ I(1/x * a) + b * x is the best model of those tried here for this curve
# it fits nicely on the plot and has the best goodness of fit statistic
# no doubt with a better understanding of nls and the data a better fitting
# function could be found. Perhaps the optimisation method here might be
# useful also: http://stats.stackexchange.com/a/21098/7744

Second method: use genetic programming to search a vast amount of models

This seems to be a kind of wild shot in the dark approach to curve-fitting. You don't have to specify much at the start, though perhaps I'm doing it wrong...

# symbolic regression using Genetic Programming
# http://rsymbolic.org/projects/rgp/wiki/Symbolic_Regression
library(rgp)
# this will probably take some time and throw
# a lot of warnings...
result1 <- symbolicRegression(y ~ x, 
             data=dat, functionSet=mathFunctionSet,
             stopCondition=makeStepsStopCondition(2000))
# inspect results, they'll be different every time...
(symbreg <- result1$population[[which.min(sapply(result1$population, result1$fitnessFunction))]])

function (x) 
tan((x - x + tan(x)) * x) 
# quite bizarre...

# inspect visual fit
ggplot() + geom_point(data=dat, aes(x,y), size = 3) +
  geom_line(data=data.frame(symbx=dat$x, symby=sapply(dat$x, symbreg)), aes(symbx, symby), colour = "red")

Actually a very poor visual fit. Perhaps there's a bit more effort required to get quality results from genetic programming...

Credits: Curve fitting answer 1, curve fitting answer 2 by G. Grothendieck.

这篇关于将曲线拟合到特定数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆