class_docstr: Training pipeline for the matrix factorization model.
  
  ``MatrixFactorizationModel`` models have an embedding layer for both users and items which are
  dot-producted together to output a single float ranking value.
  
  Collie adds a twist on to this incredibly popular framework by allowing separate optimizers
  for embeddings and bias terms. With larger datasets and multiple epochs of training, a model
  might incorrectly learn to only optimize the bias terms for a quicker path towards a local
  loss minimum, essentially memorizing how popular each item is. By using a separate, slower
  optimizer for the bias terms (like Stochastic Gradient Descent), the model must prioritize
  optimizing the embeddings for meaningful, more varied recommendations, leading to a model
  that is able to achieve a much lower loss. See the documentation below for ``bias_lr`` and
  ``bias_optimizer`` input arguments for implementation details.
  
  All ``MatrixFactorizationModel`` instances are subclasses of the ``LightningModule`` class
  provided by PyTorch Lightning. This means to train a model, you will need a
  ``collie.model.CollieTrainer`` object, but the model can be saved and loaded without this
  ``Trainer`` instance. Example usage may look like:
  
  .. code-block:: python
  
      from collie.model import CollieTrainer, MatrixFactorizationModel
  
  
      model = MatrixFactorizationModel(train=train)
      trainer = CollieTrainer(model)
      trainer.fit(model)
      model.eval()
  
      # do evaluation as normal with ``model``
  
      model.save_model(filename='model.pth')
      new_model = MatrixFactorizationModel(load_model_path='model.pth')
  
      # do evaluation as normal with ``new_model``
  
  Parameters
  ----------
  embedding_dim: int
      Number of latent factors to use for user and item embeddings
  dropout_p: float
      Probability of dropout
  sparse: bool
      Whether or not to treat embeddings as sparse tensors. If ``True``, cannot use weight decay
      on the optimizer
  bias_lr: float
      Bias terms learning rate. If 'infer', will set equal to ``lr``
  bias_optimizer: torch.optim or str
      Optimizer for the bias terms. This supports the same string options as ``optimizer``, with
      the addition of ``infer``, which will set the optimizer equal to ``optimizer``. If
      ``bias_optimizer`` is ``None``, only a single optimizer will be created for all model
      parameters
  y_range: tuple
      Specify as ``(min, max)`` to apply a sigmoid layer to the output score of the model to get
      predicted ratings within the range of ``min`` and ``max``
docstr: Forward pass through the model.
  
  Simple matrix factorization for a single user and item looks like:
  
  ````prediction = (user_embedding * item_embedding) + user_bias + item_bias````
  
  If dropout is added, it is applied to the two embeddings and not the biases.
  
  Parameters
  ----------
  users: tensor, 1-d
      Array of user indices
  items: tensor, 1-d
      Array of item indices
  
  Returns
  -------
  preds: tensor, 1-d
      Predicted ratings or rankings
docstr_tok: ["Forward","pass","through","the","model",".","Simple","matrix","factorization","for","a","single","user","and","item","looks","like",":","``","``","prediction","=","(","user_embedding","*","item_embedding",")","+","user_bias","+","item_bias","``","``","If","dropout","is","added",",","it","is","applied","to","the","two","embeddings","and","not","the","biases",".","Parameters","--","--","--","--","--","users",":","tensor",",","1-d","Array","of","user","indices","items",":","tensor",",","1-d","Array","of","item","indices","Returns","--","--","--","-","preds",":","tensor",",","1-d","Predicted","ratings","or","rankings"]
code: def forward(
      self, users: torch.tensor, items: torch.tensor
  ) -> torch.tensor:
      """
      Forward pass through the model.
  
      Simple matrix factorization for a single user and item looks like:
  
      ````prediction = (user_embedding * item_embedding) + user_bias + item_bias````
  
      If dropout is added, it is applied to the two embeddings and not the biases.
  
      Parameters
      ----------
      users: tensor, 1-d
          Array of user indices
      items: tensor, 1-d
          Array of item indices
  
      Returns
      -------
      preds: tensor, 1-d
          Predicted ratings or rankings
  
      """
      user_embeddings = self.user_embeddings(users)
      item_embeddings = self.item_embeddings(items)
  
      preds = (
          torch.mul(
              self.dropout(user_embeddings),
              self.dropout(item_embeddings),
          ).sum(axis=1)
          + self.user_biases(users).squeeze(1)
          + self.item_biases(items).squeeze(1)
      )
  
      if self.hparams.y_range is not None:
          preds = (
              torch.sigmoid(preds)
              * (self.hparams.y_range[1] - self.hparams.y_range[0])
              + self.hparams.y_range[0]
          )
  
      return preds
  
file_path: collie/collie/model/matrix_factorization.py
imports: from functools import partial
  from typing import Callable, Dict, Optional, Tuple, Union
  import torch
  from torch import nn
  from torch.optim.lr_scheduler import ReduceLROnPlateau
  from collie.model.base import BasePipeline, INTERACTIONS_LIKE_INPUT, ScaledEmbedding, ZeroEmbedding
  from collie.utils import get_init_arguments, merge_docstrings
label_desc: Use image node_id 3 for calling the MatrixFactorizationModel obj's underlying member method code with example usage: obj.forward(users, items) and returns: preds