在R中,我想创建一个名为budget_optimal_allocation()
的函数,它使用两个主要参数:
data
: Dataframemax_budget
:数值
该函数的目的是找到产生最佳tot_ROI的数据中每个通道的最佳花费水平。
示例 Dataframe 被构造为:
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最大。因此,该函数将优化支出向量,因此所有通道都在同一时间,而不是一个接一个。这一点非常重要,因此函数必须能够管理向量的优化,而不是一个通道一个通道地迭代循环。
在优化过程中会有一些限制:每个channel_name
花费必须在输入 Dataframe 中定义的spend_min
和spend_max
内,并且tot_spend
必须等于budget_optimal_allocation()
中定义的max_budget
。
下面的代码是我到目前为止得到的,但是
- 我不相信这是正确的方法(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)
2条答案
按热度按时间anauzrmj1#
我不认为
optim
可以解决你的问题,因为这个问题是一个带有max_budget
约束的 * 约束优化问题。一个有希望的候选者是constrOptim
。有两件事你需要注意:
1.因为你已经指定了
fnscale=-1
,你不需要在你的objective_function
中返回-tot_ROI
;否则,返回到最小化过程。1.你应该有一个
sum(spend) <= max_budget
的显式语句,这在你的约束优化问题中很关键。代码
下面是一个实现(我想把
objective_function
从budget_optimal_allocation
中移出来,因为如果你需要改变目标函数,这样更容易维护代码)输出
与你问题中的数据相同
我们将看到
如果你想 * 用尽 * 所有的预算
你可以有以下的变化
init <- (spend_min + spend_max) / 2
,ui <- rbind(diag(k), -diag(k), rep(1, k))
和ci <- c(spend_min, -spend_max, max_budget)
,所以,代码是你会看到输出
并检查是否所有预算都用完了
pu82cl6c2#
我认为你的问题可以用
optim
来解决,但你必须做一些代数运算,因为optim
更适合于无约束优化。它可以使用方法L-BFGS-B
和Brent
相对地处理边界,但没有其他约束比这更复杂。您可以使用拉格朗日乘子将简单的约束优化问题转化为无约束优化问题。本质上,定义一个与原始函数相同的函数,加上约束时间常数。
最大化L.
我对拉格朗日乘数有点生疏了,但这应该会在你每次超出预算时惩罚目标。lambda越高,你对超出预算的宽容就越少。