## Reimplementing Our Mannequin in CVXPY

Alright, now we’re able to get to that optimum answer utilizing cvxpy. First, we outline the variables, in our case one for every channel and every timestep so 3**N* = 3*200 = 600 variables in complete.

With out the rest, the optimum can be setting all variables to infinity, so we want some constraints. The variables ought to all be

- non-negative, and
- we wish the sum of all of those 600 variables to be smaller or equal to what we have now spent traditionally.

Then, we need to optimize the mannequin the mannequin that we have now carried out utilizing numpy capabilities, however utilizing their cvxpy equal as an alternative, which generally means writing `cp`

as an alternative of `np`

. We will even reuse the carryover matrix from earlier than!

`import cvxpy as cp`original_total_spends = knowledge[["TV", "Radio", "Banners"]].sum().sum()

# declaring variables to be optimized, N=200 per channel

television = cp.Variable(N)

radio = cp.Variable(N)

banners = cp.Variable(N)

# the constraints, constructive spends and a bounded complete funds

constraints = [

tv >= 0,

radio >= 0,

banners >= 0,

cp.sum(tv + radio + banners) <= original_total_spends,

]

# cvxpy formulation, the mannequin appears just like the numpy model

downside = cp.Drawback(

cp.Maximize(

tv_coef * cp.sum(1 - cp.exp(-tv_saturation * tv_carryover_matrix @ television))

+ radio_coef * cp.sum(1 - cp.exp(-radio_saturation * radio_carryover_matrix @ radio))

+ banners_coef * cp.sum(1 - cp.exp(-banners_saturation * banners_carryover_matrix @ banners))

), # just like the numpy mannequin, sum of all gross sales

constraints

)

We will now remedy this maximization downside in **very quick time** through

`downside.remedy()`# Output:

# 5054070.207463957

Good! We will get the optimum funds through `television.worth, radio.worth, banners.worth`

. You may see that the spends are sort of fixed for every week in every channel, which is possibly not as fascinating as anticipated. However optimum is perfect, so we are going to take it.

We may have gotten 5 million as an alternative of three.6 million previously. Whereas that is good to know, it’s nugatory now and may simply upset the enterprise. Nevertheless, we are able to use this logic now to optimize future advertising spends as effectively, after all!

## Additional Constraints

That’s it, now you may have a fundamental funds optimization instrument! And the great half is which you can mannequin much more constraints which may come from the enterprise. For example, the enterprise may say that the entire radio spends are fairly excessive:

`sum(radio.worth)`# Output:

# 524290.3686626207 (= 524,290.37 €)

The enterprise needs it to be lower than 300,000 €, for strategic causes that the mannequin can not know. Alright, no downside, let’s add it to the constraint set!

`constraints = [`

tv >= 0,

radio >= 0,

banners >= 0,

cp.sum(tv + radio + banners) <= original_total_spends,

cp.sum(radio) <= 300000 # new constraint

]

Simple as that. We will let the optimization run once more and we find yourself with barely diminished optimized gross sales of 4,990,178.80 €. But when we verify the sum of the radio spends now

`sum(radio.worth)`# Output:

# 299999.9992275703

we are able to see that the enterprise constraint was revered. And we are able to add much more constraints, corresponding to

- the sum of two channels must be smaller or larger than some quantity, or
- in some weeks we don’t enable any media spending.

You solely must mannequin it utilizing some sums and equalities or inequalities.

On this article, we first recapped the formulation for advertising combine fashions. This was vital as a result of we wanted to reimplement the fashions. Fortunately, since our fashions are straightforward and interpretable, this was no downside in any respect.

Our mannequin had in actual fact one other nice property: it’s concave! On this case, the utmost worth of gross sales is uniquely outlined, and we may get to it through convex optimization. Optimizing non-convex or non-concave capabilities is troublesome usually, and extra of an artwork that entails tuning many hyperparameters, that’s why we didn’t go this route.

As a grand finale, we optimized our media funds! It was about time. Now we have even seen how you can incorporate extra constraints into the mannequin, corresponding to that some channels want some minimal or most funds allocations. Utilizing this strategy, now you can optimize your future media funds allocation.

One other optimization that we didn’t speak about is **minimizing your media funds** below the constraint that you simply need to make a sure minimal quantity of gross sales, i.e. spending as little cash as you may to nonetheless attain your aim. That is one thing you can too implement your self simply! In distinction, earlier than we have now taken all the cash we have now and made as many gross sales as potential.