class_docstr: https://arxiv.org/abs/2306.02317
  BERT-based model for Spellchecking ASR Customization.
  It takes as input ASR hypothesis and candidate customization entries.
  It labels the hypothesis with correct entry index or 0.
  Example input:   [CLS] a s t r o n o m e r s _ d i d i e _ s o m o n _ a n d _ t r i s t i a n _ g l l o [SEP] d i d i e r _ s a u m o n [SEP] a s t r o n o m i e [SEP] t r i s t a n _ g u i l l o t [SEP] ...
  Input segments:      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0     1 1 1 1 1 1 1 1 1 1 1 1 1 1     2 2 2 2 2 2 2 2 2 2 2     3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3     4      
  Example output:      0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 3 3 3 3 3 3 3 3 3 3 3 3 3 0     ...
class_docstr_tok: ["https",":","\/\/arxiv.org\/abs\/2306.02317","BERT-based","model","for","Spellchecking","ASR","Customization",".","It","takes","as","input","ASR","hypothesis","and","candidate","customization","entries",".","It","labels","the","hypothesis","with","correct","entry","index","or","0",".","Example","input",":","[","CLS","]","a","s","t","r","o","n","o","m","e","r","s","_","d","i","d","i","e","_","s","o","m","o","n","_","a","n","d","_","t","r","i","s","t","i","a","n","_","g","l","l","o","[","SEP","]","d","i","d","i","e","r","_","s","a","u","m","o","n","[","SEP","]","a","s","t","r","o","n","o","m","i","e","[","SEP","]","t","r","i","s","t","a","n","_","g","u","i","l","l","o","t","[","SEP","]","...","Input","segments",":","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","1","1","1","1","1","1","1","1","1","1","1","1","1","1","2","2","2","2","2","2","2","2","2","2","2","3","3","3","3","3","3","3","3","3","3","3","3","3","3","3","3","4","Example","output",":","0","0","0","0","0","0","0","0","0","0","0","0","0","1","1","1","1","1","1","1","1","1","1","1","0","0","0","0","0","3","3","3","3","3","3","3","3","3","3","3","3","3","0","..."]
code: def __init__(self, cfg: DictConfig, trainer: Trainer = None) -> None:
      super().__init__(cfg=cfg, trainer=trainer)
  
      # Label map contains 11 labels: 0 for nothing, 1..10 for target candidate ids
      label_map_file = self.register_artifact(
          "label_map", cfg.label_map, verify_src_exists=True
      )
  
      # Semiotic classes for this model consist only of classes CUSTOM(means fragment containing custom candidate) and PLAIN (any other single-character fragment)
      # They are used only during validation step, to calculate accuracy for CUSTOM and PLAIN classes separately
      semiotic_classes_file = self.register_artifact(
          "semiotic_classes",
          cfg.semiotic_classes,
          verify_src_exists=True,
      )
      self.label_map = read_label_map(label_map_file)
      self.semiotic_classes = read_label_map(semiotic_classes_file)
  
      self.num_labels = len(self.label_map)
      self.num_semiotic_labels = len(self.semiotic_classes)
      self.id_2_tag = {
          tag_id: tag for tag, tag_id in self.label_map.items()
      }
      self.id_2_semiotic = {
          semiotic_id: semiotic
          for semiotic, semiotic_id in self.semiotic_classes.items()
      }
      self.max_sequence_len = cfg.get(
          "max_sequence_len", self.tokenizer.tokenizer.model_max_length
      )
  
      # Setup to track metrics
      # We will have (len(self.semiotic_classes) + 1) labels.
      # Last one stands for WRONG (span in which the predicted tags don't match the labels)
      # This is needed to feed the sequence of classes to classification_report during validation
      label_ids = self.semiotic_classes.copy()
      label_ids["WRONG"] = len(self.semiotic_classes)
      self.tag_classification_report = ClassificationReport(
          len(self.semiotic_classes) + 1,
          label_ids=label_ids,
          mode="micro",
          dist_sync_on_step=True,
      )
  
      self.hidden_size = cfg.hidden_size
  
      # hidden size is doubled because in forward we concatenate embeddings for characters and embeddings for subwords
      self.logits = TokenClassifier(
          self.hidden_size * 2,
          num_classes=self.num_labels,
          num_layers=1,
          log_softmax=False,
          dropout=0.1,
      )
  
      self.loss_fn = CrossEntropyLoss(logits_ndim=3)
  
      self.builder = bert_example.BertExampleBuilder(
          self.label_map,
          self.semiotic_classes,
          self.tokenizer.tokenizer,
          self.max_sequence_len,
      )
  
imports: from time import perf_counter
  from typing import Dict, Optional
  import torch
  from omegaconf import DictConfig
  from pytorch_lightning import Trainer
  from nemo.collections.common.losses import CrossEntropyLoss
  from nemo.collections.nlp.data.spellchecking_asr_customization import SpellcheckingAsrCustomizationDataset, SpellcheckingAsrCustomizationTestDataset, TarredSpellcheckingAsrCustomizationDataset, bert_example
  from nemo.collections.nlp.data.text_normalization_as_tagging.utils import read_label_map
  from nemo.collections.nlp.metrics.classification_report import ClassificationReport
  from nemo.collections.nlp.models.nlp_model import NLPModel
  from nemo.collections.nlp.modules.common.token_classifier import TokenClassifier
  from nemo.collections.nlp.parts.utils_funcs import tensor2list
  from nemo.core.classes.common import PretrainedModelInfo, typecheck
  from nemo.core.neural_types import LogitsType, NeuralType
  from nemo.utils import logging
  from nemo.utils.decorators import experimental
label_desc: Use image node_id 4 to create a new SpellcheckingAsrCustomizationModel object from inherited base classes: NLPModel with example: obj = SpellcheckingAsrCustomizationModel(cfg, trainer)