code: def test_main(self):
      for mll in self.mlls.values():
          out = mll.model(*mll.model.train_inputs)
          loss = -mll(out, mll.model.train_targets).sum()
          loss.backward()
          params = {
              n: p for n, p in mll.named_parameters() if p.requires_grad
          }
          grads = [
              torch.zeros_like(p) if p.grad is None else p.grad
              for p in params.values()
          ]
  
          closure = get_loss_closure(mll)
          self.assertTrue(loss.equal(closure()))
  
          closure = get_loss_closure_with_grads(mll, params)
          _loss, _grads = closure()
          self.assertTrue(loss.equal(_loss))
          self.assertTrue(
              all(a.equal(b) for a, b in zip_longest(grads, _grads))
          )
  
file_path: botorch/test/optim/closures/test_model_closures.py
imports: from itertools import zip_longest
  from math import pi
  import torch
  from botorch.models import ModelListGP, SingleTaskGP
  from botorch.models.transforms.input import Normalize
  from botorch.models.transforms.outcome import Standardize
  from botorch.optim.closures.model_closures import get_loss_closure, get_loss_closure_with_grads
  from botorch.utils.testing import BotorchTestCase
  from gpytorch import settings
  from gpytorch.mlls import ExactMarginalLogLikelihood, SumMarginalLogLikelihood
  from torch.utils.data import DataLoader, TensorDataset
label_desc: Use image node_id 2 for calling the TestLossClosures obj's underlying member method code with example usage: obj.test_main() without return types