Skip to content

Instantly share code, notes, and snippets.

View abhijeet-talaulikar's full-sized avatar

Abhijeet Talaulikar abhijeet-talaulikar

View GitHub Profile
rolling_channel_coefficient = pm.GaussianRandomWalk(
f"coefficient_{channel}",
sigma=sigma_walk,
init_dist=pm.Normal.dist(channel_prior, 0.01),
dims="time"
)
if splits == "Q":
time_series = pd.PeriodIndex(dates, freq='Q').astype(str).str[-1].astype(int).values
elif splits == "H":
time_series = pd.PeriodIndex(dates, freq='Q').astype(str).str[-1].map({'1':1, '2':1, '3':2, '4':2}).values
elif splits == "YoY":
time_series = np.array([1]*52 + [2]*52)
else:
time_series = np.arange(104)
def BayesianMMM(splits="W"):
if splits == "Q":
time_series = pd.PeriodIndex(dates, freq='Q').astype(str).str[-1].astype(int).values
elif splits == "H":
time_series = pd.PeriodIndex(dates, freq='Q').astype(str).str[-1].map({'1':1, '2':1, '3':2, '4':2}).values
elif splits == "YoY":
time_series = np.array([1]*52 + [2]*52)
else:
time_series = np.arange(104)
# Value of the objective function (ROI)
print(f"The Optimal Objective Value {opt_model.objVal}")
# Values of decision variables (Funds allocated to each channel)
opt_df = pd.DataFrame.from_dict(x_vars, orient="index", columns=["Variable Object"])
opt_df.reset_index(inplace=True)
opt_df.rename(columns={"index": "Media"}, inplace=True)
opt_df["Budget Allocated"] = opt_df["Variable Object"].apply(lambda item: item.X)
plt.bar(opt_df["Media"], opt_df["Budget Allocated"])
plt.xlabel("Media")
# initialize model
opt_model = grb.Model(name="Media Budget Optimization")
x_vars = opt_model.addVars(media_roi['media'], vtype=grb.GRB.CONTINUOUS,
lb=0, name="media")
# keep total spend less than new available budget
opt_model.addConstr(sum(x_vars[i] for i in media_roi['media']) <=
new_budget, name="New Budget")
current_revenue = media_roi['revenue'].sum()
current_budget = media_roi['spend'].sum()
new_budget = current_budget * 1.05
posterior = pm.sample_posterior_predictive(trace, mmm)
predictions = posterior['posterior_predictive']['revenue'].mean(axis=0).mean(axis=0) * media['REVENUE'].mean()
media_decomp = pd.DataFrame({i:np.array(trace['posterior']["contribution_"+str(i)]).mean(axis=(0,1)) for i in channel_priors.keys()}, index=dates) * media['REVENUE'].mean()
plt.plot(media['REVENUE'])
plt.plot(predictions)
plt.title("Model Fit")
def get_response_curve(channel, start_time, end_time):
def hill_transform(x, alpha, gamma):
return 1 / (1 + (x/gamma)**-alpha)
# parameters
coefficient = model.query("variable == @channel")['coefficient'].iloc[0]
alpha = model.query("variable == @channel")['alpha'].iloc[0]
gamma = model.query("variable == @channel")['gamma'].iloc[0]
media_decomp = pd.DataFrame({i:np.array(trace['posterior']["contribution_"+str(i)]).mean(axis=(0,1)) for i in channel_priors.keys()}, index=dates) * media['REVENUE'].mean()
media_roi = pd.concat([
media.drop(['DATE','REVENUE'],axis=1).sum(),
media_decomp.sum()
], axis=1).reset_index()
media_roi.columns = ['media','spend','revenue']
media_roi['ROI'] = (media_roi['revenue'] / media_roi['spend'])
bias = pd.DataFrame({
"t": np.arange(104)
})
d = 2
# Fourier terms
for i in np.arange(1,d+1):
bias[f"cos_{i}"] = np.cos(2 * np.pi * i * bias["t"] / 52)
bias[f"sin_{i}"] = np.sin(2 * np.pi * i * bias["t"] / 52)