Я вычисляю коэффициенты с помощью решателя nls в R. Я изо всех сил пытаюсь реализовать процедуру оптимизации, чтобы правильно адаптировать коэффициенты к ограничению неравенства.
Цель
- свести к минимуму остатки подобранной кривой
- Выход функции
innerSolve
при заданном значении mySetpoints[1]
= 100 равен или меньше mySetpoints[2]
= 8,2e-05.
library(tidyverse)
library(plotly)
library(NlcOptim)
library(Rsolnp)
## define set curve function ----
outerSolve <- function(x, a1, a2, a3){
a1 * (1 - innerSolve(x, a2, a3) * (x - 1))
}
# part of the curve function
innerSolve <- function(x, a2, a3){
a2 * x ^ a3
}
# define set coefficents
setCoef <- c(80, 0.0002, -0.18)
# define setpoints
mySetpoints <- c(100, 0.000082)
# create sample curve with some noise
myDF <- (function(){
# define x
x = seq(50, 800, 5)
set.seed(123)
tibble(x = x,
y = outerSolve(x, setCoef[1], setCoef[2], setCoef[3]) +
rnorm(length(x), 0, 0.02)
)
})()
# start values for target coefficents
startCoef <- c(max(myDF$y), 0.0001, -0.1)
# data list with results of nls
myModel <- nls(
y ~ outerSolve(x, find.a1, find.a2, find.a3),
data = myDF,
start = c(
find.a1 = startCoef[1],
find.a2 = startCoef[2],
find.a3 = startCoef[3]
),
trace = TRUE,
control = nls.control(maxiter = 100)
)
При текущих коэффициентах выходной сигнал при заданном значении равен
innerSolve(mySetpoints[1], coef(myModel)[2], coef(myModel)[3])
find.a2
8.679169e-05
Есть идеи, как к этому подойти?
Редактировать
В настоящее время работаю с пакетом Rsolnp
, который идет в правильном направлении, но я не смог получить удовлетворительные результаты.
# minimize this function
minFunction <- function(giveCoef){
myDF %>%
mutate(predicted.y = outerSolve(x, giveCoef[1], giveCoef[2], giveCoef[3]),
squaredRes = (y - predicted.y) ^ 2
) %>%
summarise(sum.squaredRes = sum(squaredRes)) %>%
pull(sum.squaredRes)
}
# consider this non linear inequality constrain
constrainFunction = function(x){
mySetpoints[2] - innerSolve(mySetpoints[1], a2 = x[2], a3 = x[3])
}
# save optimized coefficients
optimResult <- solnp(startCoef, minFunction, ineqfun = constrainFunction,
ineqUB = 100, ineqLB = 0,
LB = c(0, 0, -1), UB = c(150, 1, 0))$par
innerSolve(mySetpoints[1], optimResult[2], optimResult[3])
Таким образом, вывод функции innerSolve
на заданном значении в порядке (6.811625e-05), но коэффициенты 2 и 3 действительно далеки от массива setCoef
.
optimResult
[1] 7.980713e+01 9.741321e-05 -7.768357e-02
Редактировать 2
С пакетом NlcOptim
и равными ограничениями я получаю довольно хорошие результаты.
# constraint function for NlcOptim package
confun1 = function(x){
f <- mySetpoints[2] - x[2] * mySetpoints[1] ^ x[3]
return(list(ceq = f, c = NULL))
}
# save optimized coefficients
optimResult1 <- solnl(X = startCoef, objfun = minFunction, confun = confun1)$par
# output
innerSolve(mySetpoints[1], optimResult1[2], optimResult1[3])
[1] 8.200001e-05
optimResult1
[,1]
[1,] 80.005610025
[2,] 0.000154733
[3,] -0.137884531