拟合多元多项式的分数

时间:2016-09-26 11:32:07

标签: r regression nls non-linear-regression

如何拟合以下形式的多元分数多项式:

给定函数:y = f(x,z),两个变量xz的函数。更具体地说,它的形式为:

y = (x^2 + x^3)/(z^2 + z^3)

分子是预测器x的第3度的多项式,分母也是某个预测器z的第3度的多项式。

我想为每个预测变量xz拟合多项式,即我需要找到系数A,B,C,D:

y = (A*x^2 + B*x^3)/(C*z^2 + D*z^3)

基本上,y是度数为3的两个多项式的比率。如何拟合这样的函数?

以下数据框的示例。 我不能发布完整的数据框,因为它有超过1000行。

y = c(-4.10594369806545, -4.23691458506868, -4.24690667936422, -3.53677470254628, -4.30406509320417, -4.19442802077908, -4.66857169733859, -2.82271310942235, -4.19720194766181, 3.52164353473802, -4.3917019001973, -5.41654474791269, 2.87471821731616, -3.85922481986118, -4.25370811223789, -3.57887855889961, -5.33913936106829, -4.11775265312012, -2.89958841300109, -4.18661983833127)

x = c(8.06526520889773, 9.39897529082673,9.07348918922699,7.5522372875608, 9.17294998275762,5.77455154554441, 9.2005930205213, 8.07309119969315, 7.42177579364465,8.18896686364888, 8.07868822922987, 8.50956416425175,9.71269017726113, 7.98378106897745, 7.69893619981345, 8.49576524400262, 8.02224091680654,8.25400859056484, 7.58171964012531, 8.35655484545343)

z = c(2.56494935746154, 4.99043258677874, 4.43081679884331,3.66356164612965,4.53259949315326,1.79175946922805,4.23410650459726, 5.38449506278909,3.13549421592915,4.34380542185368, 3.43398720448515,2.77258872223978,6.94985645500077,3.97029191355212, 3.40119738166216,4.39444915467244,2.19722457733622,3.91202300542815,4.06044301054642, 3.87120101090789)

dat = data.frame(cbind(y=y,x=x,z=z))

更新

致电nls

nls(y~(a*(x**2) + b*(x**3))/(c*(z**2) + d*(z**3)), dat, start=list(a=1,b=1,c=1,d=1))

1 个答案:

答案 0 :(得分:2)

这是一个很好的问题,你在这里。至少我从中学到了一些东西。但是,我觉得这个问题更多地围绕这个特定任务(大学任务?)的解决方案而不是一般性问题。

但是让我分享解决方案的方法: 我们在这里有什么

eq1

可以简化为

enter image description here

解决y ^ \ theta在数值上变得更容易管理。 正如我们所看到的(并且在努力尝试并且未能解决非线性问题之后),它实际上是两个线性模型的划分。因此,一种方法是分别估计这两个问题的系数。我们修复系数ab以查找cd,然后使用cd查找ab

以下代码解决了系数

首先是一些数据

library(dplyr)

sampleData <- data.frame(x = runif(100, -100, 100), z = runif(100, -100, 100)) %>%
  mutate(y = ( (-2 * x^2) + (5 * x^3) ) /  (-4 * z^2 + 6 * z^3)) %>%
  mutate(zxfactor = z^2/x^2,
         yy = y * zxfactor)

现在我们解决yy。有一些随机起始值...

init2 <- structure(runif(4, -10, 10), names=c("A", "B", "C", "D"))
coefab <- init2[c("A", "B")]
coefcd <- init2[c("C", "D")]

...我们需要通过

拟合ab的线性模型

enter image description here

和<{p}}的cd的线性模型

enter image description here

# don't use for loop but determine a terminal condition... but i'm too lazy :-)
for(i in 1:100) {
  # make linear prediction using coeff. c and d
  sampleData <- sampleData %>%
    mutate(yab = yy * (coefcd[1] + coefcd[2] * z))
  # and fit a model for a and b
  coefab <- coef(lm(yab ~ x, sampleData))
  # then make a linear prediction using coeff. a and b
  sampleData <- sampleData %>%
    mutate(ycd = (coefab[1] + coefab[2] * x) / yy)
  # and fit a model for c and d
  coefcd <- coef(lm(ycd ~ z, sampleData))
} # repeat until satisfied

coefab
coefcd

我们对找到的系数感到满意吗?让我们检查:

optimFun <- function(params, out, x, z) {
  res <- (params[1] + params[2]*x)/(params[3] + params[4]*z)
  return( sqrt(sum( (out - res)^2 )) )
}

optimFun(c(coefab, coefcd), x = sampleData$x, z = sampleData$z, out = sampleData$yy)

> optimFun(c(coefab, coefcd), x = sampleData$x, z = sampleData$z, out = sampleData$yy)
[1] 1.951043e-12

确实,我们因为建模的函数估计与数据yy(缩放的)之间的差异接近于零。由于问题是超定的,因此不同的迭代导致不同的参数估计。 (也许有人可以更详细地解释一下)

评论:

  • 估算值比nls
  • 确定的估算值更接近零
  • 如果您想使用optim,可以使用optimFun。为了更快收敛,您甚至可以定义派生函数
  • 这是一个很好的问题,可以显示一般优化可能会失败的地方,并且总是值得考虑手头的问题。
  • 尝试lm(yyz ~ x, data = sampleData %>% mutate(yyz = yy*(-4 + 6*z))) ,它会返回a = -2b = 5的确切值。给定任意两个参数,您可以找到最小化函数的匹配对。