code: def _fit(self, quadruplets, weights=None):
      quadruplets = self._prepare_inputs(
          quadruplets, type_of_inputs="tuples"
      )
  
      # check to make sure that no two constrained vectors are identical
      vab = quadruplets[:, 0, :] - quadruplets[:, 1, :]
      vcd = quadruplets[:, 2, :] - quadruplets[:, 3, :]
      if vab.shape != vcd.shape:
          raise ValueError("Constraints must have same length")
      if weights is None:
          self.w_ = np.ones(vab.shape[0])
      else:
          self.w_ = weights
      self.w_ /= self.w_.sum()  # weights must sum to 1
      M, prior_inv = _initialize_metric_mahalanobis(
          quadruplets,
          self.prior,
          return_inverse=True,
          strict_pd=True,
          matrix_name="prior",
          random_state=self.random_state,
      )
  
      step_sizes = np.logspace(-10, 0, 10)
      # Keep track of the best step size and the loss at that step.
      l_best = 0
      s_best = self._total_loss(M, vab, vcd, prior_inv)
      if self.verbose:
          print("initial loss", s_best)
      for it in range(1, self.max_iter + 1):
          grad = self._gradient(M, vab, vcd, prior_inv)
          grad_norm = scipy.linalg.norm(grad)
          if grad_norm < self.tol:
              break
          if self.verbose:
              print("gradient norm", grad_norm)
          M_best = None
          for step_size in step_sizes:
              step_size /= grad_norm
              new_metric = M - step_size * grad
              w, v = scipy.linalg.eigh(new_metric)
              new_metric = v.dot((np.maximum(w, 1e-8) * v).T)
              cur_s = self._total_loss(new_metric, vab, vcd, prior_inv)
              if cur_s < s_best:
                  l_best = step_size
                  s_best = cur_s
                  M_best = new_metric
          if self.verbose:
              print(
                  "iter",
                  it,
                  "cost",
                  s_best,
                  "best step",
                  l_best * grad_norm,
              )
          if M_best is None:
              break
          M = M_best
      else:
          if self.verbose:
              print(
                  "Didn't converge after",
                  it,
                  "iterations. Final loss:",
                  s_best,
              )
      self.n_iter_ = it
  
      self.components_ = components_from_metric(M)
      return self
  
imports: import numpy
  import scipy.linalg
  from sklearn.base import TransformerMixin
  from .base_metric import _QuadrupletsClassifierMixin, MahalanobisMixin
  from .constraints import Constraints
  from ._util import components_from_metric, _initialize_metric_mahalanobis
  import warnings
label_desc: Use image node_id 2 for calling the _BaseLSML obj's underlying member method code with example usage: obj._fit(quadruplets, weights) and returns: self