code: def _unpack(m, num_rows, hash2index, seed=1, fill=None):
      """Restore the array to its natural shape, undoing the optimization.
  
      A packed matrix contains contiguous vectors for ngrams, as well as a hashmap.
      The hash map maps the ngram hash to its index in the packed matrix.
      To unpack the matrix, we need to do several things:
  
      1. Restore the matrix to its "natural" shape, where the number of rows
         equals the number of buckets.
      2. Rearrange the existing rows such that the hashmap becomes the identity
         function and is thus redundant.
      3. Fill the new rows with random values.
  
      Parameters
      ----------
  
      m : np.ndarray
          The matrix to restore.
      num_rows : int
          The number of rows that this array should have.
      hash2index : dict
          the product of the optimization we are undoing.
      seed : float, optional
          The seed for the PRNG.  Will be used to initialize new rows.
      fill : float or array or None, optional
          Value for new rows. If None (the default), randomly initialize.
      Returns
      -------
      np.array
          The unpacked matrix.
  
      Notes
      -----
  
      The unpacked matrix will reference some rows in the input matrix to save memory.
      Throw away the old matrix after calling this function, or use np.copy.
  
      """
      orig_rows, *more_dims = m.shape
      if orig_rows == num_rows:
          #
          # Nothing to do.
          #
          return m
      assert num_rows > orig_rows
  
      if fill is None:
          rand_obj = np.random
          rand_obj.seed(seed)
  
          #
          # Rows at the top of the matrix (the first orig_rows) will contain "packed" learned vectors.
          # Rows at the bottom of the matrix will be "free": initialized to random values.
          #
          m = _pad_random(m, num_rows - orig_rows, rand_obj)
      else:
          m = np.concatenate([m, [fill] * (num_rows - orig_rows)])
  
      #
      # Swap rows to transform hash2index into the identify function.
      # There are two kinds of swaps.
      # First, rearrange the rows that belong entirely within the original matrix dimensions.
      # Second, swap out rows from the original matrix dimensions, replacing them with
      # randomly initialized values.
      #
      # N.B. We only do the swap in one direction, because doing it in both directions
      # nullifies the effect.
      #
      swap = {
          h: i for (h, i) in hash2index.items() if h < i < orig_rows
      }
      swap.update(
          {h: i for (h, i) in hash2index.items() if h >= orig_rows}
      )
      for h, i in swap.items():
          assert h != i
          m[[h, i]] = m[[i, h]]  # swap rows i and h
  
      return m
  
imports: import logging
  import numpy
  from numpy import ones, vstack, float32
  import gensim.models._fasttext_bin
  from gensim.models.word2vec import Word2Vec
  from gensim.models.keyedvectors import KeyedVectors, prep_vectors
  from gensim import utils
  from gensim.utils import deprecated
  from gensim.models import keyedvectors
label_desc: Use image node_id 8 for calling a global function with example usage: _unpack(m, num_rows, hash2index, seed, fill) and returns: m, m