多项式近似比

Ratio of polynomials approximation

我正在尝试将多项式拟合到我的数据集,看起来像这样(完整数据集位于 post 的末尾):

理论预测曲线的公式为:

看起来像这样(x 介于 0 和 1 之间):

当我尝试通过以下方式在 R 中制作线性模型时:

mod <- lm(y ~ poly(x, 2, raw=TRUE)/poly(x, 2))

我得到以下曲线:

这与我的预期大不相同。您是否知道如何根据这些数据拟合一条新曲线,使其与理论预测的曲线相似?另外,它应该只有一个最小值。

完整数据集:


x 值向量:

x <- c(0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.11, 0.12,
 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25,
 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38,
 0.39, 0.40, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51,
 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.62, 0.63, 0.64,
 0.65, 0.66, 0.67, 0.68, 0.69, 0.70, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77,
 0.78, 0.79, 0.80, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.90,
 0.91, 0.92, 0.93, 0.94, 0.95)

y 值向量:

y <- c(4.104,  4.444,  4.432,  4.334,  4.285,  4.058,  3.901,  4.382,
  4.258,  4.158,  3.688,  3.826,  3.724,  3.867,  3.811,  3.550,  3.736, 3.591,
  3.566,  3.566,  3.518,  3.581,  3.505,  3.454,  3.529,  3.444,  3.501,  3.493,
  3.362,  3.504,  3.365,  3.348,  3.371,  3.389,  3.506,  3.310,  3.578,  3.497,
  3.302,  3.530,  3.593,  3.630,  3.420,  3.467,  3.656,  3.644,  3.715,  3.698,
  3.807,  3.836,  3.826,  4.017,  3.942,  4.208,  3.959,  3.856,  4.157,  4.312,
  4.349,  4.286,  4.483,  4.599,  4.395,  4.811,  4.887,  4.885,  5.286,  5.422,
  5.527,  5.467,  5.749,  5.980,  6.242,  6.314,  6.587,  6.790,  7.183,  7.450,
  7.487,  8.566,  7.946,  9.078,  9.308, 10.267, 10.738, 11.922, 12.178, 13.243,
  15.627, 16.308, 19.246, 22.022, 25.223, 29.752)

既然你已经有了理论上的预测,你似乎不需要新的模型,它实际上只是一个绘图任务:

 png(); plot(y~x)
 lines(x,mod,col="blue")
 dev.off()

您不能期望 lm 对非线性问题产生很好的近似。该理论表达式中涉及 x 的分母使其具有固有的非线性。

使用nls拟合非线性模型。请注意,模型公式并非如问题中所示那样唯一定义,因为如果我们将所有系数乘以任何数字,结果仍将给出相同的预测。为了避免这种情况,我们需要固定一个系数。第一次尝试使用问题中显示的系数作为起始值(固定一个除外)但失败了,因此尝试删除 C 并将得到的系数输入到 C = 1 的第二次拟合中。

 st <- list(a = 43, b = -14, c = 25, B = 18)
 fm <- nls(y ~ (a + b * x + c * x^2) / (9 + B * x), start = st)
 fm2 <- nls(y ~ (a + b * x + c * x^2) / (9 + B * x + C * x^2), start = c(coef(fm), C = 1))

 plot(y ~ x)
 lines(fitted(fm2) ~ x, col = "red")

(图表后续)

注意:这里是一个使用nls2随机搜索获取起始值的例子。我们假设每个系数都在 -50 和 50 之间。

library(nls2)

set.seed(123) # for reproducibility
v <- c(a = 50, b = 50, c = 50, B = 50, C = 50)
st0 <- as.data.frame(rbind(-v, v))
fm0 <- nls2(y ~ (a + b * x + c * x^2) / (9 + B * x + C * x^2), start = st0,
   alg = "random", control = list(maxiter = 1000))

fm3 <- nls(y ~ (a + b * x + c * x^2) / (9 + B * x + C * x^2), st = coef(fm0))