This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def hill_transform(x, alpha, gamma): | |
return 1 / (1 + (x/gamma)**-alpha) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
media = pd.read_csv('media.csv', parse_dates=['DATE']) | |
media = media.resample('W-Mon', label='left', closed='left', on='DATE').sum() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
channel_priors = { | |
"CTV": 0.02, | |
"DISPLAY": 0.05, | |
"DIRECT_MAIL": 0.02, | |
"EMAIL": 0.03, | |
"PAID_SOCIAL": 0.08, | |
"PAID_SEARCH": 0.14, | |
"TV": 0.01 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# define coefficient | |
channel_prior = channel_priors[channel] | |
channel_coefficient = pm.TruncatedNormal(f"coefficient_{channel}", mu=channel_prior, sigma=0.0001, lower=0, upper=0.15) | |
# define saturation | |
alpha = pm.Uniform(f"alpha_{channel}", lower=0.5, upper=2) | |
gamma = pm.Uniform(f"gamma_{channel}", lower=0.5, upper=1.5) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def scale(x, y): | |
return x * y.sum() / x.sum() | |
with pm.Model() as mmm: | |
target = media_transformed['REVENUE'] / media_transformed['REVENUE'].mean() | |
media_contributions = [] | |
for channel in channel_priors.keys(): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trace_vars = [i.replace('coefficient_','') for i in dir(trace['posterior']) if i.startswith("coefficient_") or i=='intercept'] | |
trace_coeff_vars = [i for i in dir(trace['posterior']) if i.startswith("coefficient_") or i=='intercept'] | |
trace_alpha_vars = [i for i in dir(trace['posterior']) if i.startswith("alpha_")] | |
trace_gamma_vars = [i for i in dir(trace['posterior']) if i.startswith("gamma_")] | |
model_results = pd.DataFrame({ | |
"variable": trace_vars, | |
"coefficient": [float(trace['posterior'][i].mean()) for i in trace_coeff_vars] | |
}).merge( | |
pd.DataFrame({ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
az.plot_posterior( | |
trace, | |
var_names=['intercept', 'coefficient_'], | |
filter_vars='like' | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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']) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | |