def _fit_model(
    self,
    validate_percent: Optional[float] = None,
    print_interval: int = 20,
    run_name: str = "",
  ) -> Tuple[float, float, Optional[float]]:
    """Run gradient descent to train the model.

    Args:
        mf_model (BiasedMatrixFactorization)
        optimizer (torch.optim.Optimizer)
        criterion (torch.nn.modules.loss._Loss)
        row (torch.LongTensor)
        col (torch.LongTensor)
        rating (torch.FloatTensor)
    """
    assert self.mf_model is not None
    self._create_train_validate_sets(validate_percent)
    assert self.trainModelData is not None

    prev_loss = 1e10
    loss = self._get_loss()
    epoch = 0

    while (abs(loss.item() - prev_loss) > self._convergence) and (
      not (epoch > 100 and loss.item() > prev_loss)
    ):
      prev_loss = loss.item()

      # Backpropagate
      loss.backward()

      # Update the parameters
      self.optimizer.step()

      # Set gradients to zero
      self.optimizer.zero_grad()

      # Predict and calculate loss
      loss = self._get_loss(epoch=epoch)

      if epoch % print_interval == 0:
        self._compute_and_print_loss(loss.item(), epoch, run_name=run_name, final=False)
        # Log histograms with adaptive handling

      epoch += 1

    if self._log:
      logger.info(f"Num epochs: {epoch}")
    return self._compute_and_print_loss(loss.item(), epoch, run_name=run_name, final=True)
Run gradient descent to train the model.

    Args:
        mf_model (BiasedMatrixFactorization)
        optimizer (torch.optim.Optimizer)
        criterion (torch.nn.modules.loss._Loss)
        row (torch.LongTensor)
        col (torch.LongTensor)
        rating (torch.FloatTensor)
    
sourcecode/scoring/matrix_factorization/matrix_factorization.py