code: def read_lexicon(path: str, vocab_source: Dict[str, int], vocab_target: Dict[str, int]) -> np.ndarray:
      
      src_unk_id = vocab_source[C.UNK_SYMBOL]
      trg_unk_id = vocab_target[C.UNK_SYMBOL]
      lexicon = np.zeros((len(vocab_source), len(vocab_target)))
      n = 0
      for src_id, trg_id, prob in lexicon_iterator(path, vocab_source, vocab_target):
          if src_id == src_unk_id:
              continue
          if trg_id == trg_unk_id:
              lexicon[src_id, trg_unk_id] += prob
          else:
              lexicon[src_id, trg_id] = prob
          n += 1
      logger.info("Loaded lexicon from '%s' with %d entries", path, n)
      return lexicon
docs: Loads lexical translation probabilities from a translation table of format: src, trg, logprob.
      Source words unknown to vocab_source are discarded.
      Target words unknown to vocab_target contribute to p(unk|source_word).
      See Incorporating Discrete Translation Lexicons into Neural Machine Translation, Section 3.1 & Equation 5
      (https://arxiv.org/pdf/1606.02006.pdf))
  
      :param path: Path to lexicon file.
      :param vocab_source: Source vocabulary.
      :param vocab_target: Target vocabulary.
      :return: Lexicon array. Shape: (vocab_source_size, vocab_target_size).