class_docstr: Create an ``Interactions``-like object for data in the HDF5 format that might be too large to
  fit in memory.
  
  Many of the same features of ``Interactions`` are implemented here, with the exception that
  approximate negative sampling will always be used.
  
  Parameters
  ----------
  hdf5_path: str
  user_col: str
      Column in HDF5 file with user IDs. IDs must begin at 0
  item_col: str
      Column in HDF5 file with item IDs. IDs must begin at 0
  num_negative_samples: int
      Number of negative samples to return with each ``__getitem__`` call
  num_users: int
      Number of users in the dataset. If ``num_users == 'infer'`` and there is not a ``meta`` key
      in ``hdf5_path``'s HDF5 dataset, this will be set to the the maximum value in
      ``user_col`` + 1, found by iterating through the entire dataset
  num_items: int
      Number of items in the dataset. If ``num_items == 'infer'`` and there is not an ``meta`` key
      in ``hdf5_path``'s HDF5 dataset, this will be set to the the maximum value in
      ``item_col`` + 1, found by iterating through the entire dataset
  seed: int
      Seed for random sampling and shuffling if ``shuffle is True``
  shuffle: bool
      Shuffle data in a batch. For example, if one calls ``__getitem__`` with
      ``start_idx_and_batch_size = (0, 4)`` and ``shuffle is False``, this will always return the
      data at indices 0, 1, 2, 3 in order. However, the same call with ``shuffle = True`` will
      return a random shuffle of 0, 1, 2, 3 each call. This is recommended for use in a
      ``HDF5InteractionsDataLoader`` for training data in lieu of true data shuffling
class_docstr_tok: ["Create","an","``","Interactions","``","-like","object","for","data","in","the","HDF5","format","that","might","be","too","large","to","fit","in","memory",".","Many","of","the","same","features","of","``","Interactions","``","are","implemented","here",",","with","the","exception","that","approximate","negative","sampling","will","always","be","used",".","Parameters","--","--","--","--","--","hdf5_path",":","str","user_col",":","str","Column","in","HDF5","file","with","user","IDs",".","IDs","must","begin","at","0","item_col",":","str","Column","in","HDF5","file","with","item","IDs",".","IDs","must","begin","at","0","num_negative_samples",":","int","Number","of","negative","samples","to","return","with","each","``","__getitem__","``","call","num_users",":","int","Number","of","users","in","the","dataset",".","If","``","num_users","==","'infer","'","``","and","there","is","not","a","``","meta","``","key","in","``","hdf5_path","``","'s","HDF5","dataset",",","this","will","be","set","to","the","the","maximum","value","in","``","user_col","``","+","1",",","found","by","iterating","through","the","entire","dataset","num_items",":","int","Number","of","items","in","the","dataset",".","If","``","num_items","==","'infer","'","``","and","there","is","not","an","``","meta","``","key","in","``","hdf5_path","``","'s","HDF5","dataset",",","this","will","be","set","to","the","the","maximum","value","in","``","item_col","``","+","1",",","found","by","iterating","through","the","entire","dataset","seed",":","int","Seed","for","random","sampling","and","shuffling","if","``","shuffle","is","True","``","shuffle",":","bool","Shuffle","data","in","a","batch",".","For","example",",","if","one","calls","``","__getitem__","``","with","``","start_idx_and_batch_size","=","(","0",",","4",")","``","and","``","shuffle","is","False","``",",","this","will","always","return","the","data","at","indices","0",",","1",",","2",",","3","in","order",".","However",",","the","same","call","with","``","shuffle","=","True","``","will","return","a","random","shuffle","of","0",",","1",",","2",",","3","each","call",".","This","is","recommended","for","use","in","a","``","HDF5InteractionsDataLoader","``","for","training","data","in","lieu","of","true","data","shuffling"]
code: def __init__(
      self,
      hdf5_path: str,
      user_col: str = "users",
      item_col: str = "items",
      num_negative_samples: int = 10,
      num_users: int = "infer",
      num_items: int = "infer",
      seed: Optional[int] = None,
      shuffle: bool = False,
  ):
      self.hdf5_path = hdf5_path
      self.user_col = user_col
      self.item_col = item_col
      self.num_negative_samples = num_negative_samples
      self.seed = seed
      self.shuffle = shuffle
  
      with pd.HDFStore(
          self.hdf5_path, mode="r", complib="blosc"
      ) as store:
          self.num_interactions = store.get_storer("interactions").shape
  
          if isinstance(num_users, int) and isinstance(num_items, int):
              self.num_users = num_users
              self.num_items = num_items
          else:
              try:
                  chunk = store.select("meta")
                  self.num_users = chunk["num_users"].item()
                  self.num_items = chunk["num_items"].item()
              except KeyError:
                  print(
                      "``meta`` key not found - generating ``num_users`` and ``num_items``."
                  )
  
                  self.num_users = 0
                  self.num_items = 0
                  # while we are here, we can also check minimum IDs are 0 for free
                  # TODO: is there a more efficient way to check this? should we always check?
                  min_user_id = 1
                  min_item_id = 1
  
                  # default Pandas ``chunksize`` is 100000, so we will use that too
                  chunksize = 100000
                  for idx in tqdm(
                      range(0, self.num_interactions, chunksize)
                  ):
                      chunk = store.select(
                          "interactions",
                          start=idx,
                          stop=(idx + chunksize),
                      )
                      self.num_users = max(
                          chunk[self.user_col].max(), self.num_users
                      )
                      self.num_items = max(
                          chunk[self.item_col].max(), self.num_items
                      )
                      min_user_id = min(
                          chunk[self.user_col].min(), min_user_id
                      )
                      min_item_id = min(
                          chunk[self.item_col].min(), min_item_id
                      )
  
                  if min_user_id != 0 or min_item_id != 0:
                      raise ValueError(
                          f"Minimum values of {user_col} and {item_col} in HDF5 data must both be"
                          f" 0, not {min_user_id} and {min_item_id}, respectively."
                      )
  
                  # add one here since ``users`` and ``items`` are both zero-indexed
                  self.num_users += 1
                  self.num_items += 1
  
      assert self.num_users > 1
      assert self.num_items > 1
  
      if self.seed is None:
          self.seed = collie.utils.get_random_seed()
  
      np.random.seed(seed=self.seed)
  
imports: from abc import ABCMeta, abstractmethod
  import collections
  import random
  import textwrap
  from typing import Any, Iterable, List, Optional, Tuple, Union
  import warnings
  import numpy
  import pandas
  from scipy.sparse import coo_matrix, dok_matrix
  import torch
  from tqdm.auto import tqdm
  import collie
label_desc: Use image node_id 1 to create a new HDF5Interactions object from inherited base classes: torch.utils.data with example: obj = HDF5Interactions(hdf5_path, user_col, item_col, num_negative_samples, num_users, num_items, seed, shuffle)