I am currently trying to port a soccer model to Pyro. It looks about right on my end but was hoping anyone had some insight on any possible traps.
http://danielweitzenfeld.github.io/passtheroc/blog/2014/10/28/bayes-premier-league/
#hyperpriors
home = pymc.Normal('home', 0, .0001, value=0)
tau_att = pymc.Gamma('tau_att', .1, .1, value=10)
tau_def = pymc.Gamma('tau_def', .1, .1, value=10)
intercept = pymc.Normal('intercept', 0, .0001, value=0)
#team-specific parameters
atts_star = pymc.Normal("atts_star",
mu=0,
tau=tau_att,
size=num_teams,
value=att_starting_points.values)
defs_star = pymc.Normal("defs_star",
mu=0,
tau=tau_def,
size=num_teams,
value=def_starting_points.values)
# trick to code the sum to zero contraint
@pymc.deterministic
def atts(atts_star=atts_star):
atts = atts_star.copy()
atts = atts - np.mean(atts_star)
return atts
@pymc.deterministic
def defs(defs_star=defs_star):
defs = defs_star.copy()
defs = defs - np.mean(defs_star)
return defs
@pymc.deterministic
def home_theta(home_team=home_team,
away_team=away_team,
home=home,
atts=atts,
defs=defs,
intercept=intercept):
return np.exp(intercept +
home +
atts[home_team] +
defs[away_team])
@pymc.deterministic
def away_theta(home_team=home_team,
away_team=away_team,
home=home,
atts=atts,
defs=defs,
intercept=intercept):
return np.exp(intercept +
atts[away_team] +
defs[home_team])
home_goals = pymc.Poisson('home_goals',
mu=home_theta,
value=observed_home_goals,
observed=True)
away_goals = pymc.Poisson('away_goals',
mu=away_theta,
value=observed_away_goals,
observed=True)
The above is the PYMC3 variant.
I believe ported over to Pyro this is the following.
def hierarchical_football(home_team, away_team, home_obs_goals, away_obs_goals, num_teams):
home = pyro.sample("home", dist.Normal(0, .0001))
intercept = pyro.sample("intercept", dist.Normal(0, .0001))
tau_att = pyro.sample(
"tau_att", dist.Gamma(.1, .1)
)
tau_def = pyro.sample(
"tau_def", dist.Gamma(.1, .1)
)
with pyro.plate("plate_i", num_teams):
atts_star = pyro.sample("atts_star", dist.Normal(0.0, tau_att))
defs_star = pyro.sample("defs_star", dist.Normal(0.0, tau_def))
atts = pyro.deterministic("atts", atts_star - atts_star.mean() )
defs = pyro.deterministic("defs", defs_star - defs_star.mean() )
home_theta = pyro.deterministic("home_theta", torch.exp(intercept + home + atts[home_team] + defs[away_team]) )
away_theta = pyro.deterministic("away_theta", torch.exp(intercept + atts[away_team] + defs[home_team]) )
home_goals = pyro.sample('home_goals', dist.Poisson(home_theta), obs=home_obs_goals )
away_goals = pyro.sample('away_goals', dist.Poisson(away_theta), obs=away_obs_goals )
return home_goals, away_goals
Does the above make sense as far as a port?
One of the open end defects is I couldnt figure out how to set initial starting values in Pyro.