code: def test_empirical_distribution(hybridize: bool) -> None:
      r"""
      This verifies if the loss implemented by `EmpiricalDistribution` is correct.
      This is done by recovering parameters of a parametric distribution not by maximizing likelihood but by
      optimizing CRPS loss on the Monte Carlo samples drawn from the underlying parametric distribution.
  
      More precisely, given observations `obs` drawn from the true distribution p(x; \theta^*), we solve
  
                  \theta_hat = \argmax_{\theta} CRPS(obs, {x}_i)
                               subject to:      x_i ~ p(x; \theta)
  
      and verify if \theta^* and \theta_hat agree.
  
      This test uses Multivariate Gaussian with diagonal covariance. Once multivariate CRPS is implemented in
      `EmpiricalDistribution` one could use `LowrankMultivariateGaussian` as well. Any univariate distribution whose
      `sample_rep` is differentiable can also be used in this test.
  
      """
      num_obs = 2000
      dim = 2
  
      # Multivariate CRPS is not implemented in `EmpiricalDistribution`.
      rank = 0
      W = None
  
      mu = np.arange(0, dim) / float(dim)
      D = np.eye(dim) * (np.arange(dim) / dim + 0.5)
      Sigma = D
  
      distr = LowrankMultivariateGaussian(
          mu=mx.nd.array([mu]),
          D=mx.nd.array([np.diag(D)]),
          W=W,
          dim=dim,
          rank=rank,
      )
  
      obs = distr.sample(num_obs).squeeze().asnumpy()
  
      theta_hat = maximum_likelihood_estimate_sgd(
          EmpiricalDistributionOutput(
              num_samples=100,
              distr_output=LowrankMultivariateGaussianOutput(
                  dim=dim, rank=rank, sigma_init=0.2, sigma_minimum=0.0
              ),
          ),
          obs,
          learning_rate=PositiveFloat(0.01),
          num_epochs=PositiveInt(10),
          init_biases=None,  # todo we would need to rework biases a bit to use it in the multivariate case
          hybridize=hybridize,
      )
  
      mu_hat, D_hat = theta_hat
      W_hat = None
  
      distr = LowrankMultivariateGaussian(
          dim=dim,
          rank=rank,
          mu=mx.nd.array([mu_hat]),
          D=mx.nd.array([D_hat]),
          W=W_hat,
      )
  
      Sigma_hat = distr.variance.asnumpy()
  
      print(mu_hat, Sigma_hat)
  
      assert np.allclose(
          mu_hat, mu, atol=0.2, rtol=0.1
      ), f"mu did not match: mu = {mu}, mu_hat = {mu_hat}"
  
      assert np.allclose(
          Sigma_hat, Sigma, atol=0.1, rtol=0.1
      ), f"sigma did not match: sigma = {Sigma}, sigma_hat = {Sigma_hat}"
  
imports: from functools import reduce
  from typing import List, Tuple
  import mxnet
  import numpy
  import pytest
  from gluonts.mx.model.tpp.distribution import Loglogistic, LoglogisticOutput, Weibull, WeibullOutput
  from gluonts.mx.distribution import Beta, BetaOutput, Binned, BinnedOutput, Categorical, CategoricalOutput, Dirichlet, DirichletMultinomial, DirichletMultinomialOutput, DirichletOutput, DistributionOutput, EmpiricalDistributionOutput, Gamma, GammaOutput, Gaussian, GaussianOutput, GenPareto, GenParetoOutput, Laplace, LaplaceOutput, LogitNormal, LogitNormalOutput, LowrankMultivariateGaussian, LowrankMultivariateGaussianOutput, MultivariateGaussian, MultivariateGaussianOutput, NegativeBinomial, NegativeBinomialOutput, OneInflatedBeta, OneInflatedBetaOutput, PiecewiseLinear, PiecewiseLinearOutput, Poisson, PoissonOutput, StudentT, StudentTOutput, ZeroAndOneInflatedBeta, ZeroAndOneInflatedBetaOutput, ZeroInflatedBeta, ZeroInflatedBetaOutput, ZeroInflatedNegativeBinomialOutput, ZeroInflatedPoissonOutput
  from gluonts.mx.distribution.box_cox_transform import InverseBoxCoxTransform, InverseBoxCoxTransformOutput
  from gluonts.mx.distribution.transformed_distribution import TransformedDistribution
  from gluonts.mx.distribution.transformed_distribution_output import TransformedDistributionOutput
  from gluonts.pydantic import PositiveFloat, PositiveInt
label_desc: Use image node_id 12 for calling a global function with example usage: test_empirical_distribution(hybridize) without return types