code: def initialize_params(self):
      # return a dict of per-site params as funsor.tensor.Tensors
      params = {
          "e_g": {},
          "theta_g": {},
          "eps_g": {},
          "e_i": {},
          "theta_i": {},
          "eps_i": {},
          "zi_step": {},
          "step": {},
          "angle": {},
          "zi_omega": {},
          "omega": {},
      }
  
      # size parameters
      N_v = self.config["sizes"]["random"]
      N_state = self.config["sizes"]["state"]
  
      # initialize group-level random effect parameters
      if self.config["group"]["random"] == "discrete":
          params["e_g"]["probs"] = Tensor(
              pyro.param(
                  "probs_e_g",
                  lambda: torch.randn((N_v,)).abs(),
                  constraint=constraints.simplex,
              ),
              OrderedDict(),
          )
  
          params["eps_g"]["theta"] = Tensor(
              pyro.param(
                  "theta_g",
                  lambda: torch.randn((N_v, N_state, N_state)),
              ),
              OrderedDict(
                  [("e_g", Bint[N_v]), ("y_prev", Bint[N_state])]
              ),
          )
  
      elif self.config["group"]["random"] == "continuous":
          # note these are prior values, trainable versions live in guide
          params["eps_g"]["loc"] = Tensor(
              torch.zeros((N_state, N_state)),
              OrderedDict([("y_prev", Bint[N_state])]),
          )
  
          params["eps_g"]["scale"] = Tensor(
              torch.ones((N_state, N_state)),
              OrderedDict([("y_prev", Bint[N_state])]),
          )
  
      # initialize individual-level random effect parameters
      N_c = self.config["sizes"]["group"]
      if self.config["individual"]["random"] == "discrete":
          params["e_i"]["probs"] = Tensor(
              pyro.param(
                  "probs_e_i",
                  lambda: torch.randn((N_c, N_v)).abs(),
                  constraint=constraints.simplex,
              ),
              OrderedDict(
                  [("g", Bint[N_c])]
              ),  # different value per group
          )
  
          params["eps_i"]["theta"] = Tensor(
              pyro.param(
                  "theta_i",
                  lambda: torch.randn((N_c, N_v, N_state, N_state)),
              ),
              OrderedDict(
                  [
                      ("g", Bint[N_c]),
                      ("e_i", Bint[N_v]),
                      ("y_prev", Bint[N_state]),
                  ]
              ),
          )
  
      elif self.config["individual"]["random"] == "continuous":
          params["eps_i"]["loc"] = Tensor(
              torch.zeros((N_c, N_state, N_state)),
              OrderedDict(
                  [("g", Bint[N_c]), ("y_prev", Bint[N_state])]
              ),
          )
  
          params["eps_i"]["scale"] = Tensor(
              torch.ones((N_c, N_state, N_state)),
              OrderedDict(
                  [("g", Bint[N_c]), ("y_prev", Bint[N_state])]
              ),
          )
  
      # initialize likelihood parameters
      # observation 1: step size (step ~ Gamma)
      params["zi_step"]["zi_param"] = Tensor(
          pyro.param(
              "step_zi_param",
              lambda: torch.ones((N_state, 2)),
              constraint=constraints.simplex,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      params["step"]["concentration"] = Tensor(
          pyro.param(
              "step_param_concentration",
              lambda: torch.randn((N_state,)).abs(),
              constraint=constraints.positive,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      params["step"]["rate"] = Tensor(
          pyro.param(
              "step_param_rate",
              lambda: torch.randn((N_state,)).abs(),
              constraint=constraints.positive,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      # observation 2: step angle (angle ~ VonMises)
      params["angle"]["concentration"] = Tensor(
          pyro.param(
              "angle_param_concentration",
              lambda: torch.randn((N_state,)).abs(),
              constraint=constraints.positive,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      params["angle"]["loc"] = Tensor(
          pyro.param(
              "angle_param_loc", lambda: torch.randn((N_state,)).abs()
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      # observation 3: dive activity (omega ~ Beta)
      params["zi_omega"]["zi_param"] = Tensor(
          pyro.param(
              "omega_zi_param",
              lambda: torch.ones((N_state, 2)),
              constraint=constraints.simplex,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      params["omega"]["concentration0"] = Tensor(
          pyro.param(
              "omega_param_concentration0",
              lambda: torch.randn((N_state,)).abs(),
              constraint=constraints.positive,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      params["omega"]["concentration1"] = Tensor(
          pyro.param(
              "omega_param_concentration1",
              lambda: torch.randn((N_state,)).abs(),
              constraint=constraints.positive,
          ),
          OrderedDict([("y_curr", Bint[N_state])]),
      )
  
      self.params = params
      return self.params
  
imports: from collections import OrderedDict
  import pyro
  import torch
  from torch.distributions import constraints
  import funsor.ops
  import funsor.torch.distributions
  from funsor.domains import Bint, Reals
  from funsor.tensor import Tensor
  from funsor.terms import Stack, Variable, to_funsor
label_desc: Use image node_id 2 for calling the Model obj's underlying member method code with example usage: obj.initialize_params() and returns: self