Given Adstock, saturation and even optional interactions within the model, the budget optimization method would seem to require these steps for a given set of candidate values (channel spend amounts) to be repeated:
create a new X with all required dates, control variables and spend candidates, either distributing the channel spend evenly or weighted across the time periods of the future period. Then also creating channel interactions manually if they are needed. This would be exactly like an out-of-sample prediction.
isn’t this assuming that 1) there are no channel interactions in the model and 2) the values for X which are put forward by the optimizer hit the saturation curve directly without adstock and thus would not be accurate? Or are the spend values X being adstocked and then hitting the saturation curve (which begs the question if the total outcome contribution is being summed even outside of the range of time in num_periods?)
@cetagostini seems like the expert if possible to shed some light on this for me?
The optimizer doesn’t predict the observed quantity but the expectation. controls and non optimized parameters are frozen during optimization. Only budgets change.
Furthermore the optimizer can and uses gradient information to search the space much more efficiently than computing a dense grid for different values of x like in your description
No I wasnt suggesting a grid, I was just saying that the ideal way to optimize the budget seems to be forecasting future values from the model taking into account everything, where the loop I mentioned is the obj function for the minimizer (pass in candidates, evaluate and return to the minimizer - repeat) ,
But, Is the process the optimizer uses just the saturation curves so that adstock is not taken into account or was my description of it above incorrect?
By default the optimizer is looking at total_contribution, which should include both adstock and saturation. I’ll let others confirm that, it has been sometime since I worked on it.
Optimizer takes into account saturation and adstock based on your model, replicating the full generative process until contribution (here `total_contribution`), if you adjust the transformation to consider interactions or anything like it, will be consider (If you are doing vanilla MMM API does are not by default there).
the ideal way to optimize the budget seems to be forecasting future values from the model taking into account everything
That’s precisely what optimizer is doing @jmallard but using a more “*clever*” pytensor methods under the hood than looping.
Can we intuitively then understand that during optimization, the candidate spends for a channel in a time period (e.g. week) have adstock applied and then the adstocked spends are input into the saturation function?
If we have say 6 weeks for the optimization period, will the process take into account lags that fall into week 7+ due to adcost?
Also - Control variables are all set to zero correct?
On the adstock topic: yes, the optimizer counts adstocked contributions that fall outside of the official optimization window.
The optimizer doesn’t consider the value of the control variables, as far as I can tell. Because the model is strictly additive, the control contribution and the media contribution are independent.