code: def _check_loss_and_grads(
      expected_loss, actual_loss, atol=1e-4, rtol=1e-4
  ):
      # copied from pyro
      expected_loss, actual_loss = funsor.to_data(
          expected_loss
      ), funsor.to_data(actual_loss)
      assert ops.allclose(
          actual_loss, expected_loss, atol=atol, rtol=rtol
      )
      names = pyro.get_param_store().keys()
      params = []
      for name in names:
          params.append(
              funsor.to_data(pyro.param(name)).unconstrained()
          )
      actual_grads = grad(
          actual_loss, params, allow_unused=True, retain_graph=True
      )
      expected_grads = grad(
          expected_loss, params, allow_unused=True, retain_graph=True
      )
      for name, actual_grad, expected_grad in zip(
          names, actual_grads, expected_grads
      ):
          if actual_grad is None or expected_grad is None:
              continue
          assert ops.allclose(
              actual_grad, expected_grad, atol=atol, rtol=rtol
          )
  
imports: import warnings
  import pytest
  import funsor
  from funsor.testing import xfail_param
  from funsor.util import get_backend
label_desc: Use image node_id 2 for calling a global function with example usage: _check_loss_and_grads(expected_loss, actual_loss, atol, rtol) without return types