code: def test_mle_bvm():
      vm = VonMises(tensor(0.0), tensor(1.0))
      hn = HalfNormal(tensor(0.8))
      b = Beta(tensor(2.0), tensor(5.0))
      while True:
          locs = vm.sample((2,))
          conc = hn.sample((2,))
          corr = b.sample()
          if torch.prod(conc, dim=-1) >= corr**2:
              break
  
      def mle_model(data):
          phi_loc = pyro.param("phi_loc", tensor(0.0), constraints.real)
          psi_loc = pyro.param("psi_loc", tensor(0.0), constraints.real)
          phi_conc = pyro.param(
              "phi_conc", tensor(1.0), constraints.positive
          )
          psi_conc = pyro.param(
              "psi_conc", tensor(1.0), constraints.positive
          )
          corr = pyro.param("corr", tensor(0.5), constraints.real)
          with pyro.plate("data", data.size(-2)):
              pyro.sample(
                  "obs",
                  SineBivariateVonMises(
                      phi_loc, psi_loc, phi_conc, psi_conc, corr
                  ),
                  obs=data,
              )
  
      def guide(data):
          pass
  
      bmv = SineBivariateVonMises(
          locs[0], locs[1], conc[0], conc[1], corr
      )
      data = bmv.sample((10_000,))
  
      pyro.clear_param_store()
      adam = pyro.optim.Adam({"lr": 0.01})
      svi = SVI(mle_model, guide, adam, loss=Trace_ELBO())
  
      losses = []
      steps = 200
      for step in range(steps):
          losses.append(svi.step(data))
  
      expected = {
          "phi_loc": locs[0],
          "psi_loc": locs[1],
          "phi_conc": conc[0],
          "psi_conc": conc[1],
          "corr": corr,
      }
      actuals = {k: v for k, v in pyro.get_param_store().items()}
  
      for k in expected.keys():
          if k in actuals:
              actual = actuals[k]
          else:
              actual = (
                  actuals["corr_weight"]
                  * actuals["phi_conc"]
                  * actuals["psi_conc"]
              )  # k == 'corr'
  
          assert_equal(expected[k].squeeze(), actual.squeeze(), 9e-2)
  
file_path: pyro/tests/distributions/test_sine_bivariate_von_mises.py
imports: import pytest
  import torch
  from scipy.special import binom
  from torch import tensor
  from torch.distributions import Beta, HalfNormal, VonMises
  import pyro
  from pyro.distributions import Geometric, constraints
  from pyro.distributions.sine_bivariate_von_mises import SineBivariateVonMises
  from pyro.infer import SVI, Trace_ELBO
  from tests.common import assert_equal
label_desc: Use image node_id 5 for calling a global function with example usage: test_mle_bvm() without return types