提问人:GNicoletti 提问时间:10/5/2023 最后编辑:ThomasIsCodingGNicoletti 更新时间:10/6/2023 访问量:97
在多个约束条件下将 Optim 与数值向量一起使用
use optim with a numeric vector under several constraints
问:
在 R 中,我想创建一个使用两个主要参数的函数:budget_optimal_allocation()
data
:数据框max_budget
:数值
该函数的目标是在产生最佳tot_ROI的数据中找到每个渠道的最佳支出水平。
示例数据框的结构如下:
example_data <- data.frame(
channel_name = c("Channel 1", "Channel 2", "Channel 3"),
a = c(5000, 8000, 6000),
b = c(0.001, 0.002, 0.0015),
c = c(-1.05, -1.2, -0.95),
spend_min = c(100, 200, 150),
spend_max = c(500, 800, 600)
)
a
,并且是响应曲线函数的(已知)参数,该函数将支出作为输入并生成渠道收入,公式如下:b
c
revenue <- a / (1 + b * (spend) ^ c)
也
tot_revenue <- sum(revenue)
tot_spend <- sum(spend)
tot_ROI
计算方式为tot_revenue/tot_spend
我们希望优化支出(针对每个渠道名称),以便tot_ROI达到最大值。因此,该函数将优化支出的 VECTOR,因此所有渠道同时进行,而不是一个接一个。这一点非常重要,因此函数必须能够管理向量的优化,而不是逐个通道迭代循环。
优化过程中会有一些限制:
每个支出都必须在输入数据框中并在输入数据框中定义,并且必须等于 中的定义。channel_name
spend_min
spend_max
tot_spend
max_budget
budget_optimal_allocation()
以下代码是我到目前为止想出的,但是
- 我不相信是正确的方法(optim 是正确的函数吗?
- 我不能做
optimal_spend
=max_budget
budget_optimal_allocation <- function(data, max_budget) {
# Extract channel names and parameters
channel_names <- data$channel_name
a <- data$a
b <- data$b
c <- data$c
spend_min <- data$spend_min
spend_max <- data$spend_max
# Objective function to maximize total ROI
objective_function <- function(spend, a, b, c) {
# Calculate total revenue and total spend
revenue <- a / (1 + b * (spend) ^ c)
tot_revenue <- sum(revenue)
tot_spend <- sum(spend)
# Calculate total ROI
tot_ROI <- tot_revenue / tot_spend
# Minimize the negative total ROI (to maximize total ROI)
return(-tot_ROI)
}
# Initial guess for spend values (equal allocation for each channel)
initial_spend <- rep(max_budget / length(channel_names), length(channel_names))
# Box constraints for spend
lower_bounds <- rep(spend_min, length(channel_names))
upper_bounds <- rep(spend_max, length(channel_names))
# Optimize spend allocation to maximize total ROI with box constraints
result <- optim(
par = initial_spend,
fn = objective_function,
a = a,
b = b,
c = c,
method = "L-BFGS-B",
lower = lower_bounds,
upper = upper_bounds,
control = list(fnscale = -1)
)
# Extract optimal spend for each channel
optimal_spend <- result$par
# Combine channel names and optimal spend into a data frame
optimal_allocation <- data.frame(
channel_name = channel_names,
optimal_spend = optimal_spend
)
return(optimal_allocation)
}
# Example data
example_data <- data.frame(
channel_name = c("Channel 1", "Channel 2", "Channel 3"),
a = c(5000, 8000, 6000),
b = c(0.001, 0.002, 0.0015),
c = c(-1.05, -1.2, -0.95),
spend_min = c(100, 200, 150),
spend_max = c(500, 800, 600)
)
# Max budget for optimization
max_budget <- 1000
# Run the optimization function
optimal_allocation <- budget_optimal_allocation(example_data, max_budget)
# Print the optimal allocation
print(optimal_allocation)
答:
我认为你的问题可以解决,但你将不得不做一些代数,因为它更适合无约束的优化。它可以相对地使用方法和 来处理边界,但没有比这更复杂的约束。optim
optim
L-BFGS-B
Brent
通过使用拉格朗日乘子,可以将简单的约束优化问题转换为无约束优化问题。从本质上讲,定义一个与原始函数相同的函数,加上约束时间的常数。
L = function(a,b,c,lambda) {objective_function(a,b,c)-lambda*(max_budget-sum(a,b,c))}
并最大化 L。
我对拉格朗日乘数有点生疏,但每次超出预算时,这都应该会惩罚目标。lambda 越高,您对超出预算的宽容就越少。
评论
我认为不能在这里解决您的问题,因为该问题是具有约束的约束优化问题。一个有前途的候选人是.optim
max_budget
constrOptim
您需要注意两件事:
既然你已经指定了,你就不需要在你的 ;否则,它将返回最小化过程。
fnscale=-1
-tot_ROI
objective_function
您应该有一个明确的语句,这在约束优化问题中至关重要。
sum(spend) <= max_budget
法典
下面是一个实现(我想移出,因为如果您需要更改目标函数,这将更容易维护代码)objective_function
budget_optimal_allocation
# Objective function to maximize total ROI
objective_function <- function(spend, a, b, c) {
# Calculate total revenue and total spend
revenue <- a / (1 + b * (spend)^c)
tot_revenue <- sum(revenue)
tot_spend <- sum(spend)
# Calculate total ROI
tot_revenue / tot_spend
}
budget_optimal_allocation <- function(data, max_budget) {
# Extract channel names and parameters
channel_names <- data$channel_name
a <- data$a
b <- data$b
c <- data$c
spend_min <- data$spend_min
spend_max <- data$spend_max
# Initial guess for spend values (equal allocation for each channel)
init <- spend_min + sqrt(.Machine$double.eps)
# Box constraints for spend
k <- nrow(data)
ui <- rbind(diag(k), -diag(k), -rep(1, k))
ci <- c(spend_min, -spend_max, -max_budget)
# Optimize spend allocation to maximize total ROI with box constraints
result <- constrOptim(
theta = init,
f = objective_function,
a = a,
b = b,
c = c,
ui = ui,
ci = ci,
method = "Nelder-Mead",
control = list(fnscale = -1)
)
# Combine channel names and optimal spend into a data frame
return(list(
optimal_allocation = data.frame(
channel_name = channel_names,
optimal_spend = result$par
),
max_tot_ROI = result$value
))
}
输出
使用与您的问题中相同的数据
# Example data
example_data <- data.frame(
channel_name = c("Channel 1", "Channel 2", "Channel 3"),
a = c(5000, 8000, 6000),
b = c(0.001, 0.002, 0.0015),
c = c(-1.05, -1.2, -0.95),
spend_min = c(100, 200, 150),
spend_max = c(500, 800, 600)
)
# Max budget for optimization
max_budget <- 1000
# Run the optimization function
optimal_allocation <- budget_optimal_allocation(example_data, max_budget)
我们拭目以待
> optimal_allocation
$optimal_allocation
channel_name optimal_spend
1 Channel 1 100
2 Channel 2 200
3 Channel 3 150
$max_tot_ROI
[1] 42.2219
如果你想用完所有的预算
您可以进行以下更改,因此,代码是init <- (spend_min + spend_max) / 2
ui <- rbind(diag(k), -diag(k), rep(1, k))
ci <- c(spend_min, -spend_max, max_budget)
budget_optimal_allocation <- function(data, max_budget) {
# Extract channel names and parameters
channel_names <- data$channel_name
a <- data$a
b <- data$b
c <- data$c
spend_min <- data$spend_min
spend_max <- data$spend_max
# Initial guess for spend values (equal allocation for each channel)
eps <- sqrt(.Machine$double.eps)
init <- (spend_min + spend_max) / 2
# Box constraints for spend
k <- nrow(data)
ui <- rbind(diag(k), -diag(k), rep(1, k))
ci <- c(spend_min, -spend_max, max_budget)
# Optimize spend allocation to maximize total ROI with box constraints
result <- constrOptim(
theta = init,
f = objective_function,
a = a,
b = b,
c = c,
ui = ui,
ci = ci,
method = "Nelder-Mead",
control = list(fnscale = -1)
)
# Combine channel names and optimal spend into a data frame
return(list(
optimal_allocation = data.frame(
channel_name = channel_names,
optimal_spend = result$par
),
max_tot_ROI = result$value
))
}
您将看到输出
> optimal_allocation
$optimal_allocation
channel_name optimal_spend
1 Channel 1 252.1112
2 Channel 2 427.5322
3 Channel 3 320.3566
$max_tot_ROI
[1] 18.99994
并验证所有预算是否已用完
> sum(optimal_allocation$optimal_allocation$optimal_spend)
[1] 1000
评论
sum(optimal_spend)
max_budget
ui
ci
max_budget
spend
上一个:Kotlin 舍入整数
下一个:R:R 中的多项式公式
评论