无法将曲线拟合到数据集
Trouble fitting curve to data set
在过去的两天里,我一直在尝试将曲线拟合到以下数据集。正如您(从图像中)看到的那样,数据本身形成了一条近乎完美的曲线,但我还没有找到一种方法来在数学上表示插值和外推的数据。
y = c(0.2966, 0.2793, 0.2147, 0.1523, 0.1177, 0.1026, 0.0934, 0.0767,
0.0729, 0.0693, 0.0658, 0.0624, 0.0561, 0.0502, 0.0424, 0.04, 0.0356,
0.0335, 0.0316, 0.0279, 0.0231, 0.0217, 0.0203, 0.019, 0.02, 0.016,
0.0151, 0.0134, 0.0127, 0.0119, 0.0113, 0.0106, 0.01, 0.0094, 0.0089,
0.0084, 0.0074, 0.007, 0.0062, 0.0059, 0.0053, 0.0048, 0.0043,
0.0041, 0.0037, 0.0033, 0.0032, 0.003, 0.0029, 0.0025, 0.0024,
0.0023, 0.0021, 0.002, 0.0016, 0.0016, 0.0014, 0.0012, 0.001,
0.0007, 0.0006, 0.0004, 0.0003)
x = c(0.77894, 0.79452, 0.85683, 0.92694, 0.97367, 0.99704, 1.01262,
1.04378, 1.05157, 1.05936, 1.06714, 1.07493, 1.09051, 1.10609,
1.12946, 1.13725, 1.15283, 1.16062, 1.16841, 1.18399, 1.20735,
1.21514, 1.22293, 1.23072, 1.2463, 1.25409, 1.26188, 1.27746,
1.28525, 1.29304, 1.30083, 1.30862, 1.3164, 1.32419, 1.33198,
1.33977, 1.35535, 1.36314, 1.37872, 1.38651, 1.40209, 1.41767,
1.43325, 1.44103, 1.45661, 1.47219, 1.47998, 1.48777, 1.49556,
1.51893, 1.52672, 1.53451, 1.55009, 1.55788, 1.58903, 1.59682,
1.6124, 1.63577, 1.67472, 1.75261, 1.79156, 1.86945, 1.92398)
这是用指数曲线(粉红色)和四阶多项式(红色)绘制的数据。指数曲线在四阶拟合时有相当大的误差,但您不能使用它进行推断,并且在应用于类似数据集时它并不总是有效。
对于我正在做的事情,我真的需要一些完全适合曲线的东西,但我还没有想出如何去做。谢谢
LOESS 回归似乎可以很好地处理该数据。
plot(y~x)
ls <- loess(y~x, span = 0.5)
pr <- predict(ls, x)
lines(x, pr, col = "red", lwd = 2)
看起来四阶 B 样条效果很好:
library("splines")
m0 <- lm(y~bs(x,degree=4)) ## default: 5 df
m1 <- lm(y~bs(x,degree=4,df=6))
e1 <- glm(y~x,family=gaussian(link="log"))
par(las=1,bty="l")
plot(x,y,log="y")
lines(x,predict(m0))
lines(x,predict(m1),col=2)
lines(x,predict(e1,type="response"),col=4)
关于外推风险的实物教训。
在没有理论模型的情况下,使用 logistic 函数 (f1(...)
) 或缩放的对数正态密度函数 (f2(...)
),您的数据的拟合效果大致相同。可能还有其他功能也很适合。
df <- data.frame(x,y)
library(minpack.lm) # for nlsLM(...)
f1 <- function(x,a,b,c,d) a*exp(-(b*x))/(1+c*exp(-d*x))
fit.1 <- nlsLM(y~f1(x,a,b,c,d), df,
start=c(a=1, b=1, c=100, d=0), control=list(maxiter=500))
f2 <- function(x,a,m,s) a*dlnorm(x, meanlog=m, sdlog=s)
fit.2 <- nlsLM(y~f2(x,a,m,s), df,
start=c(a=1, m=0, s=1), control=list(maxiter=500))
plot(y~x,df)
curve(predict(fit.1,data.frame(x)),add=TRUE, col="blue")
curve(predict(fit.2,data.frame(x)),add=TRUE, col="red")
但是看看当你推断时会发生什么。
plot(y~x, df, xlim=c(0.5,2), ylim=c(0,.6))
curve(predict(fit.1,data.frame(x)),add=TRUE, col="blue")
curve(predict(fit.2,data.frame(x)),add=TRUE, col="red")
事实证明,实际上对数正态密度函数拟合得更好一些,因为残差更接近正态,尽管在这两种情况下残差都有很强的模式。关键是,仅通过查看数据和拟合曲线,您可能会接受任一函数,但它们在外推时会给出截然不同的结果,事实上,两者都不是很好的拟合。你真的需要一个理论模型。
双对数图倾向于显示较大值的线性行为(即幂律),随后会混合成更陡峭的斜率。看起来你可以将这个图建模为直线加指数,但右边的外推是不确定的。
这个模型是
log(y) = a.log(x) + b - c.d^log(x)
或
y = A.x^B.exp(-C.x^D)
在过去的两天里,我一直在尝试将曲线拟合到以下数据集。正如您(从图像中)看到的那样,数据本身形成了一条近乎完美的曲线,但我还没有找到一种方法来在数学上表示插值和外推的数据。
y = c(0.2966, 0.2793, 0.2147, 0.1523, 0.1177, 0.1026, 0.0934, 0.0767,
0.0729, 0.0693, 0.0658, 0.0624, 0.0561, 0.0502, 0.0424, 0.04, 0.0356,
0.0335, 0.0316, 0.0279, 0.0231, 0.0217, 0.0203, 0.019, 0.02, 0.016,
0.0151, 0.0134, 0.0127, 0.0119, 0.0113, 0.0106, 0.01, 0.0094, 0.0089,
0.0084, 0.0074, 0.007, 0.0062, 0.0059, 0.0053, 0.0048, 0.0043,
0.0041, 0.0037, 0.0033, 0.0032, 0.003, 0.0029, 0.0025, 0.0024,
0.0023, 0.0021, 0.002, 0.0016, 0.0016, 0.0014, 0.0012, 0.001,
0.0007, 0.0006, 0.0004, 0.0003)
x = c(0.77894, 0.79452, 0.85683, 0.92694, 0.97367, 0.99704, 1.01262,
1.04378, 1.05157, 1.05936, 1.06714, 1.07493, 1.09051, 1.10609,
1.12946, 1.13725, 1.15283, 1.16062, 1.16841, 1.18399, 1.20735,
1.21514, 1.22293, 1.23072, 1.2463, 1.25409, 1.26188, 1.27746,
1.28525, 1.29304, 1.30083, 1.30862, 1.3164, 1.32419, 1.33198,
1.33977, 1.35535, 1.36314, 1.37872, 1.38651, 1.40209, 1.41767,
1.43325, 1.44103, 1.45661, 1.47219, 1.47998, 1.48777, 1.49556,
1.51893, 1.52672, 1.53451, 1.55009, 1.55788, 1.58903, 1.59682,
1.6124, 1.63577, 1.67472, 1.75261, 1.79156, 1.86945, 1.92398)
这是用指数曲线(粉红色)和四阶多项式(红色)绘制的数据。指数曲线在四阶拟合时有相当大的误差,但您不能使用它进行推断,并且在应用于类似数据集时它并不总是有效。
对于我正在做的事情,我真的需要一些完全适合曲线的东西,但我还没有想出如何去做。谢谢
LOESS 回归似乎可以很好地处理该数据。
plot(y~x)
ls <- loess(y~x, span = 0.5)
pr <- predict(ls, x)
lines(x, pr, col = "red", lwd = 2)
看起来四阶 B 样条效果很好:
library("splines")
m0 <- lm(y~bs(x,degree=4)) ## default: 5 df
m1 <- lm(y~bs(x,degree=4,df=6))
e1 <- glm(y~x,family=gaussian(link="log"))
par(las=1,bty="l")
plot(x,y,log="y")
lines(x,predict(m0))
lines(x,predict(m1),col=2)
lines(x,predict(e1,type="response"),col=4)
关于外推风险的实物教训。
在没有理论模型的情况下,使用 logistic 函数 (f1(...)
) 或缩放的对数正态密度函数 (f2(...)
),您的数据的拟合效果大致相同。可能还有其他功能也很适合。
df <- data.frame(x,y)
library(minpack.lm) # for nlsLM(...)
f1 <- function(x,a,b,c,d) a*exp(-(b*x))/(1+c*exp(-d*x))
fit.1 <- nlsLM(y~f1(x,a,b,c,d), df,
start=c(a=1, b=1, c=100, d=0), control=list(maxiter=500))
f2 <- function(x,a,m,s) a*dlnorm(x, meanlog=m, sdlog=s)
fit.2 <- nlsLM(y~f2(x,a,m,s), df,
start=c(a=1, m=0, s=1), control=list(maxiter=500))
plot(y~x,df)
curve(predict(fit.1,data.frame(x)),add=TRUE, col="blue")
curve(predict(fit.2,data.frame(x)),add=TRUE, col="red")
但是看看当你推断时会发生什么。
plot(y~x, df, xlim=c(0.5,2), ylim=c(0,.6))
curve(predict(fit.1,data.frame(x)),add=TRUE, col="blue")
curve(predict(fit.2,data.frame(x)),add=TRUE, col="red")
事实证明,实际上对数正态密度函数拟合得更好一些,因为残差更接近正态,尽管在这两种情况下残差都有很强的模式。关键是,仅通过查看数据和拟合曲线,您可能会接受任一函数,但它们在外推时会给出截然不同的结果,事实上,两者都不是很好的拟合。你真的需要一个理论模型。
双对数图倾向于显示较大值的线性行为(即幂律),随后会混合成更陡峭的斜率。看起来你可以将这个图建模为直线加指数,但右边的外推是不确定的。
这个模型是
log(y) = a.log(x) + b - c.d^log(x)
或
y = A.x^B.exp(-C.x^D)