class_docstr: History contains the information about the training history of
  a :class:`.NeuralNet`, facilitating some of the more common tasks
  that are occur during training.
  
  When you want to log certain information during training (say, a
  particular score or the norm of the gradients), you should write
  them to the net's history object.
  
  It is basically a list of dicts for each epoch, that, again,
  contains a list of dicts for each batch. For convenience, it has
  enhanced slicing notation and some methods to write new items.
  
  To access items from history, you may pass a tuple of up to four
  items:
  
    1. Slices along the epochs.
    2. Selects columns from history epochs, may be a single one or a
       tuple of column names.
    3. Slices along the batches.
    4. Selects columns from history batchs, may be a single one or a
       tuple of column names.
  
  You may use a combination of the four items.
  
  If you select columns that are not present in all epochs/batches,
  only those epochs/batches are chosen that contain said columns. If
  this set is empty, a ``KeyError`` is raised.
  
  Examples
  --------
  >>> # ACCESSING ITEMS
  >>> # history of a fitted neural net
  >>> history = net.history
  >>> # get current epoch, a dict
  >>> history[-1]
  >>> # get train losses from all epochs, a list of floats
  >>> history[:, 'train_loss']
  >>> # get train and valid losses from all epochs, a list of tuples
  >>> history[:, ('train_loss', 'valid_loss')]
  >>> # get current batches, a list of dicts
  >>> history[-1, 'batches']
  >>> # get latest batch, a dict
  >>> history[-1, 'batches', -1]
  >>> # get train losses from current batch, a list of floats
  >>> history[-1, 'batches', :, 'train_loss']
  >>> # get train and valid losses from current batch, a list of tuples
  >>> history[-1, 'batches', :, ('train_loss', 'valid_loss')]
  
  >>> # WRITING ITEMS
  >>> # add new epoch row
  >>> history.new_epoch()
  >>> # add an entry to current epoch
  >>> history.record('my-score', 123)
  >>> # add a batch row to the current epoch
  >>> history.new_batch()
  >>> # add an entry to the current batch
  >>> history.record_batch('my-batch-score', 456)
  >>> # overwrite entry of current batch
  >>> history.record_batch('my-batch-score', 789)
code: def __getitem__(self, i):
      # This implementation resolves indexing backwards,
      # i.e. starting from the batches, then progressing to the
      # epochs.
      if isinstance(i, (int, slice)):
          i = (i,)
  
      # i_e: index epoch, k_e: key epoch
      # i_b: index batch, k_b: key batch
      i_e, k_e, i_b, k_b = _unpack_index(i)
      keyerror_msg = "Key {!r} was not found in history."
  
      if i_b is not None and k_e != "batches":
          raise KeyError(
              "History indexing beyond the 2nd level is "
              "only possible if key 'batches' is used, "
              "found key {!r}.".format(k_e)
          )
  
      items = self.to_list()
  
      # extract the epochs
      # handles: history[i_e]
      if i_e is not None:
          items = items[i_e]
          if isinstance(i_e, int):
              items = [items]
  
      # extract indices of batches
      # handles: history[..., k_e, i_b]
      if i_b is not None:
          items = [row[k_e][i_b] for row in items]
  
      # extract keys of epochs or batches
      # handles: history[..., k_e]
      # handles: history[..., ..., ..., k_b]
      if k_e is not None and (i_b is None or k_b is not None):
          key = k_e if k_b is None else k_b
  
          if items:
              extract = _get_getitem_method(items[0], key)
              items = [extract(item, key) for item in items]
  
              # filter out epochs with missing keys
              items = list(filter(_not_none, items))
  
          if not items and not (k_e == "batches" and i_b is None):
              # none of the epochs matched
              raise KeyError(keyerror_msg.format(key))
  
          if (
              isinstance(i_b, slice)
              and k_b is not None
              and not any(batches for batches in items)
          ):
              # none of the batches matched
              raise KeyError(keyerror_msg.format(key))
  
      if isinstance(i_e, int):
          (items,) = items
  
      return items
  
imports: import json
  import pickle
  from skorch.utils import open_file_like
label_desc: Use image node_id 8 for calling the History obj's underlying member method code with example usage: obj.__getitem__(i) and returns: items