Hello.
I’m trying to structure a hierarchical regression problem modeling sales by location and the type of item within our marketing hierarchy.
The issues I’m running into is correctly structuring the random variable that accounts for both item and the location that item was sold. I keep getting dimensional errors.
Below is the function I use to make the different levels of each hierarchical RV.
def make_next_level_hierarchy_variable(name, mu, alpha, beta, dims=None):
with modelcontext(None):
sigma_ = pm.Gamma(f'{name}_sigma', alpha=alpha, beta=beta)
offset = pm.Normal(f'{name}_offset', dims=dims)
return pm.Deterministic(f'{name}', mu + sigma_ * offset, dims=dims)
The following is the code designating the RV that throws the dimensional error:
loc_intercept = pm.Normal('loc_intercept', mu = 0, sigma = 1)
loc_bl = utility_functions.make_next_level_hierarchy_variable(name='loc_bl', mu=loc_intercept, alpha=2, beta=1, dims=['business_line', 'location'])
loc_cat = utility_functions.make_next_level_hierarchy_variable(name='loc_cat', mu=loc_bl, alpha=2, beta=1, dims=['category', 'location'])
loc_subcat = utility_functions.make_next_level_hierarchy_variable(name='loc_subcat', mu=loc_cat, alpha=2, beta=1, dims=['subcategory', 'location'])
loc_ic = utility_functions.make_next_level_hierarchy_variable(name='loc_ic', mu=loc_subcat, alpha=2, beta=1, dims=['ic', 'location'])
loc_item = utility_functions.make_next_level_hierarchy_variable(name='loc_item', mu=loc_subcat, alpha=2, beta=1, dims=['item', 'location'])
This is how I tried to use it within the regression formula:
mu = (item_intercept[pm_item_idx] * t_[pm_time_idx] + cann_*item_cann[pm_item_idx] + **loc_item[pm_item_idx, location_idx]** + dc_discount_*dc_discount_coeff + gwp_*gwp_coeff +
count_promo_*count_promo_coeff)
For reference, there are a lot of items but only two locations.
What am I doing wrong? (if it helps…full model is below).
coords = {'business_line':business_lines,
'category':categories,
'subcategory':subcats,
'ic':ic,
'item':items,
'time':times,
'location':locations,
'yearly_components':[f'yearly_{f}_{i+1}' for f in ['cos', 'sin'] for i in range(x_fourier.shape[1] // 2)],
'weekly_components':[f'weekly_{f}_{i+1}' for f in ['cos', 'sin'] for i in range(x_fourier_week.shape[1] // 2)]}
#TRAINING THE MODEL STARTS HERE
print("fitting model...")
with pm.Model(coords=coords) as constant_model:
cat_to_bl_map = pm.Data('cat_to_bl_map', cat_to_bl_idx, mutable=False)
subcat_to_cat_map = pm.Data('subcat_to_cat_map', subcat_to_cat_idx, mutable=False)
ic_to_subcat_map = pm.Data('ic_to_subcat_map', ic_to_subcat_idx, mutable=False)
ic_to_item_map = pm.Data('ic_to_item_map', ic_to_item_idx, mutable = False)
pm_loc_idx = pm.Data('loc_idx', location_idx, mutable = True)
pm_item_idx = pm.Data('item_idx', item_idx, mutable=True)
pm_time_idx = pm.Data('time_idx', time_idx, mutable=True)
log_eaches = pm.Data('log_eaches', df.residual, mutable=True)
t_ = pm.Data('t', t, mutable = True)
# x_fourier_ = pm.Data('x_fourier', x_fourier, mutable = True)
# x_fourier_week_ = pm.Data('x_fourier_week', x_fourier_week, mutalbe = True)
cann_ = pm.Data('cannibalization', cann_idx, mutable = True)
dc_discount_ = pm.Data('dc_discount', dc_idx, mutable = True)
gwp_ = pm.Data('gwp', gwp_idx, mutable = True)
count_promo_ = pm.Data('count_promo', count_idx, mutable = True)
# month_ = pm.Data('month', month_idx, mutable = True)
mu_intercept = pm.Normal('mu_intercept', mu = 0, sigma = 10000)
bl_intercept = utility_functions.make_next_level_hierarchy_variable(name='bl_intercept', mu=mu_intercept, alpha=2, beta=1, dims=['business_line'])
cat_intercept = utility_functions.make_next_level_hierarchy_variable(name='cat_intercept', mu=bl_intercept[cat_to_bl_map], alpha=2, beta=1, dims=['category'])
subcat_intercept = utility_functions.make_next_level_hierarchy_variable(name='subcat_intercept', mu=cat_intercept[subcat_to_cat_map], alpha=2, beta=1, dims=['subcategory'])
ic_intercept = utility_functions.make_next_level_hierarchy_variable(name='ic_intercept', mu=subcat_intercept[ic_to_subcat_map], alpha=2, beta=1, dims=['ic'])
item_intercept = utility_functions.make_next_level_hierarchy_variable(name='item_intercept', mu=ic_intercept[ic_to_item_map], alpha=2, beta=1, dims=['item'])
mu_cann = pm.Normal('mu_can')
bl_cann = utility_functions.make_next_level_hierarchy_variable(name='bl_cann', mu=mu_cann, alpha=2, beta=1, dims=['business_line'])
cat_cann = utility_functions.make_next_level_hierarchy_variable(name='cat_cann', mu=bl_cann[cat_to_bl_map], alpha=2, beta=1, dims=['category'])
subcat_cann = utility_functions.make_next_level_hierarchy_variable(name='subcat_cann', mu=cat_cann[subcat_to_cat_map], alpha=2, beta=1, dims=['subcategory'])
ic_cann = utility_functions.make_next_level_hierarchy_variable(name='ic_cann', mu=subcat_cann[ic_to_subcat_map], alpha=2, beta=1, dims=['ic'])
item_cann = utility_functions.make_next_level_hierarchy_variable(name='item_cann', mu=ic_cann[ic_to_item_map], alpha=2, beta=1, dims=['item'])
loc_intercept = pm.Normal('loc_intercept', mu = 0, sigma = 1)
loc_bl = utility_functions.make_next_level_hierarchy_variable(name='loc_bl', mu=loc_intercept, alpha=2, beta=1, dims=['business_line', 'location'])
loc_cat = utility_functions.make_next_level_hierarchy_variable(name='loc_cat', mu=loc_bl, alpha=2, beta=1, dims=['category', 'location'])
loc_subcat = utility_functions.make_next_level_hierarchy_variable(name='loc_subcat', mu=loc_cat, alpha=2, beta=1, dims=['subcategory', 'location'])
loc_ic = utility_functions.make_next_level_hierarchy_variable(name='loc_ic', mu=loc_subcat, alpha=2, beta=1, dims=['ic', 'location'])
loc_item = utility_functions.make_next_level_hierarchy_variable(name='loc_item', mu=loc_subcat, alpha=2, beta=1, dims=['item', 'location'])
# location_coeff = (loc_item[pm_item_idx] * loc_intercept[pm_loc_idx]).sum(axis=1)
dc_discount_coeff = pm.Normal('dc_discount_coeff')
gwp_coeff = pm.Normal('gwp_coeff')
count_promo_coeff = pm.Normal('count_promo_coeff')
mu = (item_intercept[pm_item_idx] * t_[pm_time_idx] + cann_*item_cann[pm_item_idx] + loc_item[pm_item_idx, location_idx] + dc_discount_*dc_discount_coeff + gwp_*gwp_coeff +
count_promo_*count_promo_coeff)
sigma = pm.HalfNormal('sigma')
eaches = pm.Normal('predicted_eaches',
mu=mu,
sigma=sigma,
# lower = 0,
observed=log_eaches)