code: def feature_info(self):
      
      if self._feature_info is not None:
        return self._feature_info
  
      assert self._hparams is not None
  
      hp = self.get_hparams()
      if self.has_inputs:
        in_id = hp.input_space_id
      out_id = hp.target_space_id
  
      features = collections.defaultdict(FeatureInfo)
      for feature_name, modality_cls in six.iteritems(hp.modality):
        finfo = features[feature_name]
        finfo.modality = modality_cls
        finfo.vocab_size = hp.vocab_size[feature_name]
  
      vocabs = hp.vocabulary
      for name, encoder in six.iteritems(vocabs):
        features[name].encoder = encoder
  
      if self.has_inputs:
        features["inputs"].space_id = in_id
      features["targets"].space_id = out_id
  
      self._feature_info = features
      return features
docs: Retrieve dict<feature name, FeatureInfo>.
  
      Must first call Problem.get_hparams or Problem.dataset to have the problem's
      internal hparams already constructed.
  
      Returns:
        dict<feature name, FeatureInfo>