class_docstr: Lexicon component that stores the k most likely target words for each source word.  Used during
  decoding to restrict target vocabulary for each source sequence.
  
  :param vocab_source: Trained model source vocabulary.
  :param vocab_target: Trained mode target vocabulary.
class_docstr_tok: ["Lexicon","component","that","stores","the","k","most","likely","target","words","for","each","source","word",".","Used","during","decoding","to","restrict","target","vocabulary","for","each","source","sequence",".",":","param","vocab_source",":","Trained","model","source","vocabulary",".",":","param","vocab_target",":","Trained","mode","target","vocabulary","."]
docstr: Create from a scored lexicon file (fast_align format) using vocab from a trained Sockeye model.
  
  :param path: Path to lexicon file.
  :param k: Number of target entries per source to keep.
code: def create(self, path: str, k: int = 20):
      """
      Create from a scored lexicon file (fast_align format) using vocab from a trained Sockeye model.
  
      :param path: Path to lexicon file.
      :param k: Number of target entries per source to keep.
      """
      self.lex = np.zeros((len(self.vocab_source), k), dtype="int32")
      src_unk_id = self.vocab_source[C.UNK_SYMBOL]
      trg_unk_id = self.vocab_target[C.UNK_SYMBOL]
      num_insufficient = 0  # number of source tokens with insufficient number of translations given k
      for src_id, group in groupby(
          lexicon_iterator(path, self.vocab_source, self.vocab_target),
          key=itemgetter(0),
      ):
          # Unk token will always be part of target vocab, so no need to track it here
          if src_id == src_unk_id:
              continue
  
          # filter trg_unk_id
          filtered_group = (
              (trg_id, prob)
              for src_id, trg_id, prob in group
              if trg_id != trg_unk_id
          )
          # sort by prob and take top k
          top_k = [
              trg_id
              for trg_id, prob in sorted(
                  filtered_group, key=itemgetter(1), reverse=True
              )[:k]
          ]
          if len(top_k) < k:
              num_insufficient += 1
  
          self.lex[src_id, : len(top_k)] = top_k
  
      logger.info(
          'Created top-k lexicon from "%s", k=%d. %d source tokens with fewer than %d translations',
          path,
          k,
          num_insufficient,
          k,
      )
  
imports: import argparse
  import collections
  import os
  import sys
  import time
  import logging
  from itertools import groupby
  from operator import itemgetter
  from typing import Dict, Generator, List, Tuple, Optional
  from abc import abstractmethod, ABC
  import numpy
  from sockeye.data_io import SequenceReader
  from .None import arguments
  from .None import constants
  from .None import vocab
  from .utils import smart_open, get_tokens
  from .log import setup_main_logger, log_sockeye_version
label_desc: Use image node_id 2 for calling the TopKLexicon obj's underlying member method code with example usage: obj.create(path, k) without return types