R中的3参数非线性方程拟合
3 parameter nonlinear equation fitting in R
我正在尝试在 R 中找到一种方法,该方法允许一般方程 a*b^x + c 的参数 (a, b, c) 提供对 3 个约束随机的最佳拟合 coordinates/points(p1、p2、p3 - 坐标分别为 x1/y1、x2/y2 和 x3/y3)。
这些坐标的约束是:
- x1 和 y3 都等于 0
- x3和y1都是随机抽取的,都小于1
- x2 被分配了一个小于 x3
的随机值
- y2 被分配了一个小于 y1 的随机值
我想找到一种能够为 a、b 和 c 生成值的方法,从而生成接近 p1、p2 和 p3 的线。这只是使用 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)
但是优化函数似乎陷入局部最小值,很少产生正确的解决方案(即使使用不同的 'method' 设置)。我知道 nls 函数,但这需要选择起始值 - 我更喜欢在这个阶段不需要手动输入的方法(因为 desmos 方法能够实现)。
谢谢
给定两个零约束,我们可以通过分析将其简化为 one-parameter 问题:
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)
所以我们有一个 one-parameter 函数可以预测 y
,结合 x1 = y3 = 0
约束:
predfun <- function(b = 1, x, y) {
a <- y[1]/(1-b^x[3])
c <- y[1] - a
a*b^x +c
}
一个sum-of-squares目标函数:
target <- Vectorize(function(b) sum((y - predfun(b, x, y))^2))
可视化:
curve(target, from = -10000, to = 100000, log = "y")
现在使用optimize()
进行一维优化(我们仍然需要指定一个起始区间,虽然不是一个具体的起始点)。
optimize(target, c(-10000, 1000000))
结果:
$minimum
[1] 58928.93
$objective
[1] 2.066598e-20
我正在尝试在 R 中找到一种方法,该方法允许一般方程 a*b^x + c 的参数 (a, b, c) 提供对 3 个约束随机的最佳拟合 coordinates/points(p1、p2、p3 - 坐标分别为 x1/y1、x2/y2 和 x3/y3)。
这些坐标的约束是:
- x1 和 y3 都等于 0
- x3和y1都是随机抽取的,都小于1
- x2 被分配了一个小于 x3 的随机值
- y2 被分配了一个小于 y1 的随机值
我想找到一种能够为 a、b 和 c 生成值的方法,从而生成接近 p1、p2 和 p3 的线。这只是使用 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)
但是优化函数似乎陷入局部最小值,很少产生正确的解决方案(即使使用不同的 'method' 设置)。我知道 nls 函数,但这需要选择起始值 - 我更喜欢在这个阶段不需要手动输入的方法(因为 desmos 方法能够实现)。
谢谢
给定两个零约束,我们可以通过分析将其简化为 one-parameter 问题:
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)
所以我们有一个 one-parameter 函数可以预测 y
,结合 x1 = y3 = 0
约束:
predfun <- function(b = 1, x, y) {
a <- y[1]/(1-b^x[3])
c <- y[1] - a
a*b^x +c
}
一个sum-of-squares目标函数:
target <- Vectorize(function(b) sum((y - predfun(b, x, y))^2))
可视化:
curve(target, from = -10000, to = 100000, log = "y")
现在使用optimize()
进行一维优化(我们仍然需要指定一个起始区间,虽然不是一个具体的起始点)。
optimize(target, c(-10000, 1000000))
结果:
$minimum
[1] 58928.93
$objective
[1] 2.066598e-20