# Using a single dimensional distribution to initialize parameters for a multi dimensional distribtution

Hi, essentially what I am trying to do is the question in the title, for reference here is the problem.

I want to model hockey performance (Credit/inspiration to the rugby tutorial) and I want to make it hierarchical over the seasons. Basically I want to say that a team has an overall attack and defense score (modeled as a normal distribution around zero). I then want to use the teams overall attack and defense scores to initialize a new normal distribution for every season, representing the attack and defense scores of a team for that year.

Quick example is if there is 31 teams and 2 seasons we have a (31,) for the overall attack score then I want a per season attack score of (31, 2). Is there a way that I can do this I get a shape error when I try this.

Any help is really appreciated, thanks!

``````teams_dims = np.arange(N_TEAMS)
season_dims = np.arange(len(unique_seasons))
coords = {'teams':teams_dims, 'seasons':season_dims}
model = pm.Model(coords=coords)
with model:
# global parameters
intercept = pm.Normal('intercept', mu=0, sigma=5)

attack_sigma = pm.HalfNormal('attack_sigma', sigma=2)
defense_sigma = pm.HalfNormal('defense_sigma', sigma=2)

season_attack_sigma = pm.HalfNormal('season_attack_sigma', sigma=2)
season_defense_sigma = pm.HalfNormal('season_defense_sigma', sigma=2)

# team specific parameters
team_attack = pm.Normal('team_attack', mu=0, sigma=attack_sigma, dims='teams')
team_defense = pm.Normal('team_defense', mu=0, sigma=defense_sigma, dims='teams')

# sesason specific parameters
team_attack_season = pm.Normal('team_attack_season', mu=team_attack, sigma=season_attack_sigma, dims=('teams','seasons'))
team_defense_season = pm.Normal('team_defense_season', mu=team_defense, sigma=season_defense_sigma, dims=('teams','seasons'))

# team specific values
home_theta = tt.exp(intercept + team_attack_season[home_idx_tensor, season_idx_tensor] - team_defense_season[home_idx_tensor, season_idx_tensor])
away_theta = tt.exp(intercept + team_attack_season[home_idx_tensor, season_idx_tensor] - team_defense_season[home_idx_tensor, season_idx_tensor])

# model the goal distribution of the given teams
home_goals = pm.Poisson('home_goals', mu=home_theta, observed=home_goals_tensor)
away_goals = pm.Poisson('away_goals', mu=away_theta, observed=away_goals_tensor)
``````
``````ValueError                                Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_11968\3492909181.py in <module>
18
19     # sesason specific parameters
---> 20     team_attack_season = pm.Normal('team_attack_season', mu=team_attack, sigma=season_attack_sigma, dims=('teams','seasons'))
21     team_defense_season = pm.Normal('team_defense_season', mu=team_defense, sigma=season_defense_sigma, dims=('teams','seasons'))
22

~\.conda\envs\pymc\lib\site-packages\pymc3\distributions\distribution.py in __new__(cls, name, *args, **kwargs)
123         else:
124             dist = cls.dist(*args, **kwargs)
--> 125         return model.Var(name, dist, data, total_size, dims=dims)
126
127     def __getnewargs__(self):

~\.conda\envs\pymc\lib\site-packages\pymc3\model.py in Var(self, name, dist, data, total_size, dims)
1136             if getattr(dist, "transform", None) is None:
1137                 with self:
-> 1138                     var = FreeRV(name=name, distribution=dist, total_size=total_size, model=self)
1139                 self.free_RVs.append(var)
1140             else:

~\.conda\envs\pymc\lib\site-packages\pymc3\model.py in __init__(self, type, owner, index, name, distribution, total_size, model)
1667             self.distribution = distribution
1668             self.tag.test_value = (
-> 1669                 np.ones(distribution.shape, distribution.dtype) * distribution.default()
1670             )
1671             self.logp_elemwiset = distribution.logp(self)

ValueError: operands could not be broadcast together with shapes (31,2) (31,)

``````

Looks like itâ€™s being fussy about the shape of the `team_attack` and `team_defense`. It wants these to be column vectors so it can broadcast them across `season_attack_sigma`. Try:

``````    team_attack_season = pm.Normal('team_attack_season', mu=team_attack[:, None], sigma=season_attack_sigma, dims=('teams','seasons'))
team_defense_season = pm.Normal('team_defense_season', mu=team_defense[:, None], sigma=season_defense_sigma, dims=('teams','seasons'))
``````

The `[:, None]` adds a new dimension to the array, so it becomes `N_teams x 1` and the broadcasting works.

For the record it seemed to work as you wrote it in PyMC 4.