code: def track_model_metrics(
      model,
      train_interactions,
      test_interactions,
      k=10,
      no_epochs=100,
      no_threads=8,
      show_plot=True,
      **kwargs,
  ):
      """Function to record model's performance at each epoch, formats the performance into tidy format,
      plots the performance and outputs the performance data.
  
      Args:
          model (LightFM instance): fitted LightFM model
          train_interactions (scipy sparse COO matrix): train interactions set
          test_interactions (scipy sparse COO matrix): test interaction set
          k (int): number of recommendations, optional
          no_epochs (int): Number of epochs to run, optional
          no_threads (int): Number of parallel threads to use, optional
          **kwargs: other keyword arguments to be passed down
  
      Returns:
          pandas.DataFrame, LightFM model, matplotlib axes:
          - Performance traces of the fitted model
          - Fitted model
          - Side effect of the method
      """
      # initialising temp data storage
      model_prec_train = [0] * no_epochs
      model_prec_test = [0] * no_epochs
  
      model_rec_train = [0] * no_epochs
      model_rec_test = [0] * no_epochs
  
      # fit model and store train/test metrics at each epoch
      for epoch in range(no_epochs):
          model.fit_partial(
              interactions=train_interactions,
              epochs=1,
              num_threads=no_threads,
              **kwargs,
          )
          model_prec_train[epoch] = precision_at_k(
              model, train_interactions, k=k, **kwargs
          ).mean()
          model_prec_test[epoch] = precision_at_k(
              model, test_interactions, k=k, **kwargs
          ).mean()
  
          model_rec_train[epoch] = recall_at_k(
              model, train_interactions, k=k, **kwargs
          ).mean()
          model_rec_test[epoch] = recall_at_k(
              model, test_interactions, k=k, **kwargs
          ).mean()
  
      # collect the performance metrics into a dataframe
      fitting_metrics = pd.DataFrame(
          zip(
              model_prec_train,
              model_prec_test,
              model_rec_train,
              model_rec_test,
          ),
          columns=[
              "model_prec_train",
              "model_prec_test",
              "model_rec_train",
              "model_rec_test",
          ],
      )
      # convert into tidy format
      fitting_metrics = fitting_metrics.stack().reset_index()
      fitting_metrics.columns = ["epoch", "level", "value"]
      # exact the labels for each observation
      fitting_metrics["stage"] = fitting_metrics.level.str.split(
          "_"
      ).str[-1]
      fitting_metrics["metric"] = fitting_metrics.level.str.split(
          "_"
      ).str[1]
      fitting_metrics.drop(["level"], axis=1, inplace=True)
      # replace the metric keys to improve visualisation
      metric_keys = {"prec": "Precision", "rec": "Recall"}
      fitting_metrics.metric.replace(metric_keys, inplace=True)
      # plots the performance data
      if show_plot:
          model_perf_plots(fitting_metrics)
      return fitting_metrics, model
  
file_path: recommenders/recommenders/models/lightfm/lightfm_utils.py
imports: import pandas
  import numpy
  import seaborn
  from lightfm.evaluation import precision_at_k, recall_at_k
label_desc: Use image node_id 3 for calling a global function with example usage: track_model_metrics(model, train_interactions, test_interactions, k, no_epochs, no_threads, show_plot) and returns: fitting_metrics,  model