简体   繁体   English

R中的3参数非线性方程拟合

[英]3 parameter nonlinear equation fitting in R

I'm trying to find a method in R which allows the parameters (a, b, c) of the general equation a*b^x + c which provides the best fit to 3 constrained random coordinates/points (p1, p2, p3 - with coordinates x1/y1, x2/y2 and x3/y3 respectively).我试图在 R 中找到一种方法,它允许一般方程 a*b^x + c 的参数(a、b、c)提供最适合 3 个约束随机坐标/点(p1、p2、p3 - 坐标分别为 x1/y1、x2/y2 和 x3/y3)。

The constraints to these coordinates are:这些坐标的约束是:

  • x1 and y3 are both equal to 0 x1 和 y3 都等于 0
  • x3 and y1 are randomly both randomly selected, and less than 1 x3 和 y1 都是随机抽取的,并且都小于 1
  • x2 is assigned a random value less than x3 x2 被分配了一个小于 x3 的随机值
  • y2 is assigned a random value less than y1 y2 被分配了一个小于 y1 的随机值

I want to find a method which is able to generate values for a, b, and c which produces a line close to p1, p2 and p3.我想找到一种能够为 a、b 和 c 生成值的方法,它生成一条接近 p1、p2 和 p3 的线。 This is simply using desmos (see here for an example - https://www.desmos.com/calculator/4lmgazmrko ) but I haven't been able to find a solution in R. I've tried the following:这只是使用 desmos(示例参见此处 - https://www.desmos.com/calculator/4lmgazmrko ),但我无法在 R 中找到解决方案。我尝试了以下方法:

x <- c(0, 0.7, 0.9)
y <- c(0.9, 0.8, 0)
df_test <- as.data.frame(cbind(x, y))

predict_y_nonlinearly <- function(beta, x){
  beta[1]*(beta[2]^x) + beta[3]
}

a_nonlinearmodel <- function(beta, x, y){
  y_hat <- predict_y_nonlinearly(beta, x)
  sum((y-y_hat)^2)
}

beta <- optim(rnorm(3), a_nonlinearmodel, method = "SANN",
              y = df_test$y, x = df_test$x)$par

predict_y_nonlinearly(beta, df_test$x)

But the optimisation function appears to get stuck in local minima, and rarely produces the correct solution (even when a different 'method' setting is used).但是优化 function 似乎陷入了局部最小值,并且很少产生正确的解决方案(即使使用不同的“方法”设置)。 I'm aware of the nls function, but this requires starting values to be chosen - I'd prefer a method which does not require manual input at this stage (as the desmos method is able to achieve).我知道 nls function,但这需要选择起始值——我更喜欢在这个阶段不需要手动输入的方法(因为 desmos 方法能够实现)。

Thanks谢谢

Given the two zero constraints, we can reduce this analytically to a one-parameter problem:给定两个零约束,我们可以通过分析将其简化为单参数问题:

x1 = 0 → y1 = a + c → c = y1-a
y3 = 0 → 0 = a*b^x3 + (y1-a)
→ a*(b^x3 - 1) = -y1
→ a = y1/(1-b^x3)

So we have a one-parameter function that predicts y , incorporating the x1 = y3 = 0 constraints:所以我们有一个预测y的单参数 function,包含x1 = y3 = 0约束:

predfun <- function(b = 1, x, y)  {
  a <- y[1]/(1-b^x[3])
  c <- y[1] - a
  a*b^x +c
}

A sum-of-squares target function:平方和目标 function:

target <- Vectorize(function(b) sum((y - predfun(b, x, y))^2))

Visualize:可视化:

curve(target, from = -10000, to = 100000, log = "y")

曲线显示在负值处出现分歧,在 6e+04 附近出现明显的最小值

Now use optimize() for 1D optimization (we still need to specify a starting interval, although not a specific starting point).现在使用optimize()进行一维优化(我们仍然需要指定一个起始区间,虽然不是一个具体的起始点)。

optimize(target, c(-10000, 1000000))

Results:结果:

$minimum
[1] 58928.93

$objective
[1] 2.066598e-20

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM