docstr: Fit the Nystroem approximation and python SVM model.
  
  Parameters
  ----------
  x_ref
      Training data.
  step_size_range
      The range of values to be considered for the gradient descent step size at each iteration. This is
      specified as a tuple of the form `(min_eta, max_eta)`.
  n_step_sizes
      The number of step sizes in the defined range to be tested for loss reduction. This many points are spaced
      equidistantly along the range in log space.
  tol
      The decrease in loss required over the previous n_iter_no_change iterations in order to continue optimizing.
  n_iter_no_change
      The number of iterations over which the loss must decrease by `tol` in order for optimization to continue.
  max_iter
      The maximum number of optimization steps.
  verbose
      Verbosity level during training. ``0`` is silent, ``1`` a progress bar.
  
  Returns
  -------
  Dictionary with fit results. The dictionary contains the following keys:
      - converged: `bool` indicating whether training converged.
      - n_iter: number of iterations performed.
      - lower_bound: loss lower bound.
docstr_tok: ["Fit","the","Nystroem","approximation","and","python","SVM","model",".","Parameters","--","--","--","--","--","x_ref","Training","data",".","step_size_range","The","range","of","values","to","be","considered","for","the","gradient","descent","step","size","at","each","iteration",".","This","is","specified","as","a","tuple","of","the","form","`","(","min_eta",",","max_eta",")","`",".","n_step_sizes","The","number","of","step","sizes","in","the","defined","range","to","be","tested","for","loss","reduction",".","This","many","points","are","spaced","equidistantly","along","the","range","in","log","space",".","tol","The","decrease","in","loss","required","over","the","previous","n_iter_no_change","iterations","in","order","to","continue","optimizing",".","n_iter_no_change","The","number","of","iterations","over","which","the","loss","must","decrease","by","`","tol","`","in","order","for","optimization","to","continue",".","max_iter","The","maximum","number","of","optimization","steps",".","verbose","Verbosity","level","during","training",".","``","0","``","is","silent",",","``","1","``","a","progress","bar",".","Returns","--","--","--","-","Dictionary","with","fit","results",".","The","dictionary","contains","the","following","keys",":","-","converged",":","`","bool","`","indicating","whether","training","converged",".","-","n_iter",":","number","of","iterations","performed",".","-","lower_bound",":","loss","lower","bound","."]
code: def fit(  # type: ignore[override]
      self,
      x_ref: torch.Tensor,
      step_size_range: Tuple[float, float] = (1e-8, 1.0),
      n_step_sizes: int = 16,
      tol: float = 1e-6,
      n_iter_no_change: int = 25,
      max_iter: int = 1000,
      verbose: int = 0,
  ) -> Dict:
      """Fit the Nystroem approximation and python SVM model.
  
      Parameters
      ----------
      x_ref
          Training data.
      step_size_range
          The range of values to be considered for the gradient descent step size at each iteration. This is
          specified as a tuple of the form `(min_eta, max_eta)`.
      n_step_sizes
          The number of step sizes in the defined range to be tested for loss reduction. This many points are spaced
          equidistantly along the range in log space.
      tol
          The decrease in loss required over the previous n_iter_no_change iterations in order to continue optimizing.
      n_iter_no_change
          The number of iterations over which the loss must decrease by `tol` in order for optimization to continue.
      max_iter
          The maximum number of optimization steps.
      verbose
          Verbosity level during training. ``0`` is silent, ``1`` a progress bar.
  
      Returns
      -------
      Dictionary with fit results. The dictionary contains the following keys:
          - converged: `bool` indicating whether training converged.
          - n_iter: number of iterations performed.
          - lower_bound: loss lower bound.
      """
  
      x_nys = self.nystroem.fit(x_ref).transform(x_ref)
      n, d = x_nys.shape
      min_eta, max_eta = step_size_range
      etas = torch.tensor(
          np.linspace(np.log(min_eta), np.log(max_eta), n_step_sizes),
          dtype=x_nys.dtype,
          device=self.device,
      ).exp()
  
      # Initialise coeffs/preds/loss
      coeffs = torch.zeros(d, dtype=x_nys.dtype, device=self.device)
      intercept = torch.zeros(1, dtype=x_nys.dtype, device=self.device)
      preds = x_nys @ coeffs + intercept
      loss = self.nu * (
          coeffs.square().sum() / 2 + intercept
      ) + hinge_loss(preds)
      min_loss, min_loss_coeffs, min_loss_intercept = (
          loss,
          coeffs,
          intercept,
      )
      iter, t_since_improv = 0, 0
      converged = False
  
      with tqdm(total=max_iter, disable=not verbose) as pbar:
          while not converged:
              pbar.update(1)
              # First two lines give form of sgd update (for each candidate step size)
              sup_vec_inds = preds < 1
              cand_coeffs = (
                  coeffs[:, None] * (1 - etas * self.nu)
                  + etas * (x_nys[sup_vec_inds].sum(0) / n)[:, None]
              )
              cand_intercept = (
                  intercept - etas * self.nu + (sup_vec_inds.sum() / n)
              )
  
              # Compute loss for each candidate step size and choose the best
              cand_preds = x_nys @ cand_coeffs + cand_intercept
              cand_losses = self.nu * (
                  cand_coeffs.square().sum(0) / 2 + cand_intercept
              ) + hinge_loss(cand_preds)
              best_step_size = cand_losses.argmin()
              coeffs, intercept = (
                  cand_coeffs[:, best_step_size],
                  cand_intercept[best_step_size],
              )
              preds, loss = (
                  cand_preds[:, best_step_size],
                  cand_losses[best_step_size],
              )
  
              # Keep track of best performing coefficients and time since improving (by more than tol)
              if loss < min_loss:
                  if loss < min_loss - tol:
                      t_since_improv = 0
                  min_loss, min_loss_coeffs, min_loss_intercept = (
                      loss,
                      coeffs,
                      intercept,
                  )
              else:
                  t_since_improv += 1
  
              # Decide whether to continue
              if iter > max_iter or t_since_improv > n_iter_no_change:
                  self.coeffs = min_loss_coeffs
                  self.intercept = min_loss_intercept
                  converged = True
                  break
              else:
                  iter += 1
  
              if verbose and isinstance(pbar, tqdm):
                  pbar.set_postfix(
                      dict(loss=loss.cpu().detach().numpy().item())
                  )
  
      self._set_fitted()
      return {
          "converged": converged,
          "lower_bound": self._to_frontend_dtype(min_loss),
          "n_iter": iter,
      }
  
imports: import warnings
  from typing import Callable, Dict, Optional, Tuple
  import numpy
  import torch
  from sklearn.linear_model import SGDOneClassSVM
  from sklearn.utils.extmath import safe_sparse_dot
  from tqdm import tqdm
  from typing_extensions import Self
  from alibi_detect.od.pytorch.base import TorchOutlierDetector
  from alibi_detect.utils.pytorch.losses import hinge_loss
  from alibi_detect.utils.pytorch.kernels import GaussianRBF
  from alibi_detect.utils._types import TorchDeviceType
label_desc: Use image node_id 2 for calling the BgdSVMTorch obj's underlying member method code with example usage: obj.fit(x_ref, step_size_range, n_step_sizes, tol, n_iter_no_change, max_iter, verbose) and returns: dict