'Call `finalize` once done updating word counts. This means the
object will no longer accept new word count data, but the loose
to compact index mapping can be computed. This frees the object to
filter, subsample, and compactify incoming word arrays.
Examples
>>> corpus = Corpus()
>>> # We\'ll update the word counts, making sure that word index 2
>>> # is the most common word index.
>>> corpus.update_word_count(np.arange(1) + 2)
>>> corpus.update_word_count(np.arange(3) + 2)
>>> corpus.update_word_count(np.arange(10) + 2)
>>> corpus.update_word_count(np.arange(8) + 2)
>>> corpus.counts_loose[2]
4
>>> # The corpus has not been finalized yet, and so the compact mapping
>>> # has not yet been computed.
>>> corpus.keys_counts[0]
Traceback (most recent call last):
AttributeError: Corpus instance has no attribute \'keys_counts\'
>>> corpus.finalize()
>>> corpus.n_specials
2
>>> # The special tokens are mapped to the first compact indices
>>> corpus.compact_to_loose[0]
-2
>>> corpus.compact_to_loose[0] == corpus.specials[\'skip\']
True
>>> corpus.compact_to_loose[1] == corpus.specials[\'out_of_vocabulary\']
True
>>> corpus.compact_to_loose[2]  # Most popular token is mapped next
2
>>> corpus.loose_to_compact[3]  # 2nd most popular token is mapped next
4
>>> first_non_special = corpus.n_specials
>>> corpus.keys_counts[first_non_special] # First normal token
4'

def finalize(self):

    (self.keys_loose, self.keys_counts, n_keys) = self._loose_keys_ordered()
    self.keys_compact = np.arange(n_keys).astype('int32')
    self.loose_to_compact = {l: c for (l, c) in zip(self.keys_loose, self.keys_compact)}
    self.compact_to_loose = {c: l for (l, c) in self.loose_to_compact.items()}
    self.specials_to_compact = {s: self.loose_to_compact[i] for (s, i) in self.specials.items()}
    self.compact_to_special = {c: s for (c, s) in self.specials_to_compact.items()}
    self._finalized = True
