code: def _negative_sample_user(
      interaction_row: np.array, neg_pos_ratio: int, extra_samples: int
  ) -> Tuple[List[int], int]:
      """Returns a list of negative item indices for given user-item interactions.
  
      If there are not enough negative items, takes all of them and adds the difference to the extra_samples
      otherwise, samples with replacement.
  
      Params:
          interaction_row: user-item interaction row
          neg_pos_ratio: number of negative samples per positive sample
          extra_samples: number of additional samples to add to the negative sample list
      Returns:
          Tuple of list of negative item indices and number of extra samples
      """
      # Find all items that are not interacted with by the user
      neg_items = np.where(interaction_row == 0)[1]
      available_samples = len(neg_items)
  
      # Randomly sample negative items
      npos = interaction_row.shape[1] - len(neg_items)
      samples_required = npos * neg_pos_ratio + extra_samples
      should_sample = samples_required <= available_samples
  
      neg_items = (
          np.random.choice(neg_items, samples_required, replace=False)
          if should_sample
          else neg_items
      )
  
      return neg_items.tolist(), max(
          0, samples_required - available_samples
      )
  
file_path: ludwig/ludwig/data/negative_sampling.py
imports: import logging
  import time
  from typing import Any, List, Tuple
  import numpy
  import pandas
  import scipy
  from ludwig.utils.types import DataFrame
label_desc: Use image node_id 1 for calling a global function with example usage: _negative_sample_user(interaction_row, neg_pos_ratio, extra_samples) and returns: neg_items,  max