code: def build_argparse():
      """
      Build the argparse for the classifier.
  
      Refactored so that other utility scripts can use the same parser if needed.
      """
      parser = argparse.ArgumentParser()
  
      parser.add_argument(
          "--train",
          dest="train",
          default=True,
          action="store_true",
          help="Train the model (default)",
      )
      parser.add_argument(
          "--no_train",
          dest="train",
          action="store_false",
          help="Don't train the model",
      )
  
      parser.add_argument(
          "--shorthand",
          type=str,
          default="en_ewt",
          help="Treebank shorthand, eg 'en' for English",
      )
  
      parser.add_argument(
          "--load_name",
          type=str,
          default=None,
          help="Name for loading an existing model",
      )
      parser.add_argument(
          "--save_dir",
          type=str,
          default="saved_models/classifier",
          help="Root dir for saving models.",
      )
      parser.add_argument(
          "--save_name",
          type=str,
          default=None,
          help="Name for saving the model",
      )
      parser.add_argument(
          "--base_name",
          type=str,
          default="sst",
          help="Base name of the model to use when building a model name from args",
      )
  
      parser.add_argument(
          "--checkpoint_save_name",
          type=str,
          default=None,
          help="File name to save the most recent checkpoint",
      )
      parser.add_argument(
          "--no_checkpoint",
          dest="checkpoint",
          action="store_false",
          help="Don't save checkpoints",
      )
  
      parser.add_argument(
          "--save_intermediate_models",
          default=False,
          action="store_true",
          help="Save all intermediate models - this can be a lot!",
      )
  
      parser.add_argument(
          "--train_file",
          type=str,
          default=DEFAULT_TRAIN,
          help="Input file(s) to train a model from.  Each line is an example.  Should go <label> <tokenized sentence>.  Comma separated list.",
      )
      parser.add_argument(
          "--dev_file",
          type=str,
          default=DEFAULT_DEV,
          help="Input file(s) to use as the dev set.",
      )
      parser.add_argument(
          "--test_file",
          type=str,
          default=DEFAULT_TEST,
          help="Input file(s) to use as the test set.",
      )
      parser.add_argument(
          "--output_predictions",
          default=False,
          action="store_true",
          help="Output predictions when running the test set",
      )
      parser.add_argument("--max_epochs", type=int, default=100)
      parser.add_argument("--tick", type=int, default=2000)
  
      parser.add_argument(
          "--model_type",
          type=lambda x: ModelType[x.upper()],
          default=ModelType.CNN,
          help="Model type to use.  Options: %s"
          % " ".join(x.name for x in ModelType),
      )
  
      parser.add_argument(
          "--filter_sizes",
          default=(3, 4, 5),
          type=ast.literal_eval,
          help="Filter sizes for the layer after the word vectors",
      )
      parser.add_argument(
          "--filter_channels",
          default=1000,
          type=ast.literal_eval,
          help="Number of channels for layers after the word vectors.  Int for same number of channels (scaled by width) for each filter, or tuple/list for exact lengths for each filter",
      )
      parser.add_argument(
          "--fc_shapes",
          default="400,100",
          type=convert_fc_shapes,
          help="Extra fully connected layers to put after the initial filters.  If set to blank, will FC directly from the max pooling to the output layer.",
      )
      parser.add_argument(
          "--dropout",
          default=0.5,
          type=float,
          help="Dropout value to use",
      )
  
      parser.add_argument(
          "--batch_size",
          default=50,
          type=int,
          help="Batch size when training",
      )
      parser.add_argument(
          "--dev_eval_steps",
          default=100000,
          type=int,
          help="Run the dev set after this many train steps.  Set to 0 to only do it once per epoch",
      )
      parser.add_argument(
          "--dev_eval_scoring",
          type=lambda x: DevScoring[x.upper()],
          default=DevScoring.WEIGHTED_F1,
          help=(
              "Scoring method to use for choosing the best model.  Options: %s"
              % " ".join(x.name for x in DevScoring)
          ),
      )
  
      parser.add_argument(
          "--weight_decay",
          default=None,
          type=float,
          help="Weight decay (eg, l2 reg) to use in the optimizer",
      )
      parser.add_argument(
          "--learning_rate",
          default=None,
          type=float,
          help="Learning rate to use in the optimizer",
      )
      parser.add_argument(
          "--momentum",
          default=None,
          type=float,
          help="Momentum to use in the optimizer",
      )
  
      parser.add_argument(
          "--optim",
          default="adadelta",
          choices=["adadelta", "madgrad", "sgd"],
          help="Optimizer type: SGD, Adadelta, or madgrad.  Highly recommend to install madgrad and use that",
      )
  
      parser.add_argument(
          "--test_remap_labels",
          default=None,
          type=ast.literal_eval,
          help='Map of which label each classifier label should map to.  For example, "{0:0, 1:0, 3:1, 4:1}" to map a 5 class sentiment test to a 2 class.  Any labels not mapped will be considered wrong',
      )
      parser.add_argument(
          "--forgive_unmapped_labels",
          dest="forgive_unmapped_labels",
          default=True,
          action="store_true",
          help="When remapping labels, such as from 5 class to 2 class, pick a different label if the first guess is not remapped.",
      )
      parser.add_argument(
          "--no_forgive_unmapped_labels",
          dest="forgive_unmapped_labels",
          action="store_false",
          help="When remapping labels, such as from 5 class to 2 class, DON'T pick a different label if the first guess is not remapped.",
      )
  
      parser.add_argument(
          "--loss",
          type=lambda x: Loss[x.upper()],
          default=Loss.CROSS,
          help="Whether to use regular cross entropy or scale it by 1/log(quantity)",
      )
      parser.add_argument(
          "--loss_focal_gamma",
          default=2,
          type=float,
          help="gamma value for a focal loss",
      )
      parser.add_argument(
          "--min_train_len",
          type=int,
          default=0,
          help="Filter sentences less than this length",
      )
  
      parser.add_argument("--pretrain_max_vocab", type=int, default=-1)
      parser.add_argument(
          "--wordvec_pretrain_file",
          type=str,
          default=None,
          help="Exact name of the pretrain file to read",
      )
      parser.add_argument(
          "--wordvec_raw_file",
          type=str,
          default=None,
          help="Exact name of the raw wordvec file to read",
      )
      parser.add_argument(
          "--wordvec_dir",
          type=str,
          default="extern_data/wordvec",
          help="Directory of word vectors",
      )
      parser.add_argument(
          "--wordvec_type",
          type=lambda x: WVType[x.upper()],
          default="word2vec",
          help="Different vector types have different options, such as google 300d replacing numbers with #",
      )
      parser.add_argument(
          "--extra_wordvec_dim",
          type=int,
          default=0,
          help="Extra dim of word vectors - will be trained",
      )
      parser.add_argument(
          "--extra_wordvec_method",
          type=lambda x: ExtraVectors[x.upper()],
          default="sum",
          help="How to train extra dimensions of word vectors, if at all",
      )
      parser.add_argument(
          "--extra_wordvec_max_norm",
          type=float,
          default=None,
          help="Max norm for initializing the extra vectors",
      )
  
      parser.add_argument(
          "--charlm_forward_file",
          type=str,
          default=None,
          help="Exact path to use for forward charlm",
      )
      parser.add_argument(
          "--charlm_backward_file",
          type=str,
          default=None,
          help="Exact path to use for backward charlm",
      )
      parser.add_argument(
          "--charlm_projection",
          type=int,
          default=None,
          help="Project the charlm values to this dimension",
      )
      parser.add_argument(
          "--char_lowercase",
          dest="char_lowercase",
          action="store_true",
          help="Use lowercased characters in character model.",
      )
  
      parser.add_argument(
          "--elmo_model",
          default="extern_data/manyelmo/english",
          help="Directory with elmo model",
      )
      parser.add_argument(
          "--use_elmo",
          dest="use_elmo",
          default=False,
          action="store_true",
          help="Use an elmo model as a source of parameters",
      )
      parser.add_argument(
          "--elmo_projection",
          type=int,
          default=None,
          help="Project elmo to this many dimensions",
      )
  
      parser.add_argument(
          "--bert_model",
          type=str,
          default=None,
          help="Use an external bert model (requires the transformers package)",
      )
      parser.add_argument(
          "--no_bert_model",
          dest="bert_model",
          action="store_const",
          const=None,
          help="Don't use bert",
      )
  
      parser.add_argument(
          "--bilstm",
          dest="bilstm",
          action="store_true",
          default=True,
          help="Use a bilstm after the inputs, before the convs.  Using bilstm is about as accurate and significantly faster (because of dim reduction) than going straight to the filters",
      )
      parser.add_argument(
          "--no_bilstm",
          dest="bilstm",
          action="store_false",
          help="Don't use a bilstm after the inputs, before the convs.",
      )
      # somewhere between 200-300 seems to be the sweet spot for a couple datasets:
      # dev set macro f1 scores on 3 class problems
      # note that these were only run once each
      # more trials might narrow down which ones works best
      # es_tass2020:
      #   150        0.5580
      #   200        0.5629
      #   250        0.5586
      #   300        0.5642    <---
      #   400        0.5525
      #   500        0.5579
      #   750        0.5585
      # en_sstplus:
      #   150        0.6816
      #   200        0.6721
      #   250        0.6915    <---
      #   300        0.6824
      #   400        0.6757
      #   500        0.6770
      #   750        0.6781
      # de_sb10k
      #   150        0.6745
      #   200        0.6798    <---
      #   250        0.6459
      #   300        0.6665
      #   400        0.6521
      #   500        0.6584
      #   750        0.6447
      parser.add_argument(
          "--bilstm_hidden_dim",
          type=int,
          default=300,
          help="Dimension of the bilstm to use",
      )
  
      parser.add_argument(
          "--maxpool_width",
          type=int,
          default=1,
          help="Width of the maxpool kernel to use",
      )
  
      parser.add_argument(
          "--no_constituency_backprop",
          dest="constituency_backprop",
          default=True,
          action="store_false",
          help="When using a constituency parser, backprop into the parser's weights if True",
      )
      parser.add_argument(
          "--constituency_model",
          type=str,
          default="/home/john/stanza_resources/it/constituency/vit_bert.pt",
          help="Which constituency model to use.  TODO: make this more user friendly",
      )
      parser.add_argument(
          "--constituency_batch_norm",
          default=False,
          action="store_true",
          help="Add a LayerNorm between the output of the parser and the classifier layers",
      )
      parser.add_argument(
          "--constituency_node_attn",
          default=False,
          action="store_true",
          help="True means to make an attn layer out of the tree, with the words as key and nodes as query",
      )
      parser.add_argument(
          "--no_constituency_node_attn",
          dest="constituency_node_attn",
          action="store_false",
          help="True means to make an attn layer out of the tree, with the words as key and nodes as query",
      )
      parser.add_argument(
          "--constituency_top_layer",
          dest="constituency_top_layer",
          default=False,
          action="store_true",
          help="True means use the top (ROOT) layer of the constituents.  Otherwise, the next layer down (S, usually) will be used",
      )
      parser.add_argument(
          "--no_constituency_top_layer",
          dest="constituency_top_layer",
          action="store_false",
          help="True means use the top (ROOT) layer of the constituents.  Otherwise, the next layer down (S, usually) will be used",
      )
      parser.add_argument(
          "--constituency_all_words",
          default=False,
          action="store_true",
          help="Use all word positions in the constituency classifier",
      )
      parser.add_argument(
          "--no_constituency_all_words",
          dest="constituency_all_words",
          default=False,
          action="store_false",
          help="Use the start and end word embeddings as inputs to the constituency classifier",
      )
  
      parser.add_argument(
          "--log_norms",
          default=False,
          action="store_true",
          help="Log the parameters norms while training.  A very noisy option",
      )
  
      parser.add_argument(
          "--wandb",
          action="store_true",
          help="Start a wandb session and write the results of training.  Only applies to training.  Use --wandb_name instead to specify a name",
      )
      parser.add_argument(
          "--wandb_name",
          default=None,
          help="Name of a wandb session to start when training.  Will default to the dataset short name",
      )
  
      parser.add_argument(
          "--seed", default=None, type=int, help="Random seed for model"
      )
  
      utils.add_device_args(parser)
  
      return parser
  
imports: import argparse
  import ast
  import logging
  import os
  import random
  import re
  from enum import Enum
  import torch
  import torch.nn
  from stanza.models.common import loss
  from stanza.models.common import utils
  from stanza.models.pos.vocab import CharVocab
  import stanza.models.classifiers.data
  from stanza.models.classifiers.trainer import Trainer
  from stanza.models.classifiers.utils import WVType, ExtraVectors, ModelType
  from stanza.utils.confusion import format_confusion, confusion_to_accuracy, confusion_to_macro_f1
label_desc: Use image node_id 2 for calling a global function with example usage: build_argparse() and returns: parser