code: def _recall_at_k(
      model,
      ground_truth,
      k,
      train=None,
      user_features=None,
      item_features=None,
  ):
      # Alternative test implementation
  
      ground_truth = ground_truth.tocsr()
  
      no_users, no_items = ground_truth.shape
  
      pid_array = np.arange(no_items, dtype=np.int32)
  
      recalls = []
  
      uid_array = np.empty(no_items, dtype=np.int32)
  
      if train is not None:
          train = train.tocsr()
  
      for user_id, row in enumerate(ground_truth):
          uid_array.fill(user_id)
  
          predictions = model.predict(
              uid_array,
              pid_array,
              user_features=user_features,
              item_features=item_features,
              num_threads=4,
          )
          if train is not None:
              train_items = train[user_id].indices
              top_k = set(
                  [
                      x
                      for x in np.argsort(-predictions)
                      if x not in train_items
                  ][:k]
              )
          else:
              top_k = set(np.argsort(-predictions)[:k])
  
          true_pids = set(row.indices[row.data == 1])
  
          if true_pids:
              recalls.append(
                  len(top_k & true_pids) / float(len(true_pids))
              )
  
      return sum(recalls) / len(recalls)
  
file_path: lightfm/tests/test_evaluation.py
imports: import numpy
  import pytest
  import scipy.sparse
  from sklearn.metrics import roc_auc_score
  from lightfm.lightfm import LightFM
  from lightfm import evaluation
label_desc: Use image node_id 3 for calling a global function with example usage: _recall_at_k(model, ground_truth, k, train, user_features, item_features) and returns: unknown