code: def eval_trainer(
      trainer, dev_data, batch_mode=False, fine_grained=True
  ):
      """
      Produce dev accuracy and confusion matrix for a trainer
      """
  
      # set up confusion matrix
      tag_to_idx = dev_data.tag_to_idx
      idx_to_tag = dev_data.idx_to_tag
      confusion_matrix = {}
      for row_label in tag_to_idx:
          confusion_matrix[row_label] = {}
          for col_label in tag_to_idx:
              confusion_matrix[row_label][col_label] = 0
  
      # process dev batches
      batches = dev_data.batches
      if not batch_mode:
          batches = tqdm(batches)
      for dev_batch in batches:
          inputs = (dev_batch["sentences"], dev_batch["targets"])
          predictions = trainer.predict(inputs)
          for target_idx, prediction in zip(
              dev_batch["targets"], predictions
          ):
              prediction_label = (
                  idx_to_tag[prediction]
                  if fine_grained
                  else idx_to_tag[prediction].split("-")[0]
              )
              confusion_matrix[idx_to_tag[target_idx]][
                  prediction_label
              ] += 1
  
      # calculate dev accuracy
      total_examples = sum(
          [
              sum([confusion_matrix[i][j] for j in confusion_matrix[i]])
              for i in confusion_matrix
          ]
      )
      total_correct = sum(
          [confusion_matrix[i][i] for i in confusion_matrix]
      )
      dev_accuracy = float(total_correct) / float(total_examples)
  
      # calculate precision, recall, F1
      precision_scores = {"type": "precision"}
      recall_scores = {"type": "recall"}
      f1_scores = {"type": "f1"}
      for prediction_label in tag_to_idx:
          total = sum(
              [
                  confusion_matrix[k][prediction_label]
                  for k in tag_to_idx
              ]
          )
          if total != 0.0:
              precision_scores[prediction_label] = float(
                  confusion_matrix[prediction_label][prediction_label]
              ) / float(total)
          else:
              precision_scores[prediction_label] = 0.0
      for target_label in tag_to_idx:
          total = sum(
              [confusion_matrix[target_label][k] for k in tag_to_idx]
          )
          if total != 0:
              recall_scores[target_label] = float(
                  confusion_matrix[target_label][target_label]
              ) / float(total)
          else:
              recall_scores[target_label] = 0.0
      for label in tag_to_idx:
          if (
              precision_scores[label] == 0.0
              and recall_scores[label] == 0.0
          ):
              f1_scores[label] = 0.0
          else:
              f1_scores[label] = (
                  2.0
                  * (precision_scores[label] * recall_scores[label])
                  / (precision_scores[label] + recall_scores[label])
              )
  
      return (
          dev_accuracy,
          confusion_matrix,
          precision_scores,
          recall_scores,
          f1_scores,
      )
  
file_path: stanza/stanza/models/lang_identifier.py
imports: import argparse
  import json
  import logging
  import os
  import random
  import torch
  from datetime import datetime
  from stanza.models.common import utils
  from stanza.models.langid.data import DataLoader
  from stanza.models.langid.trainer import Trainer
  from stanza.utils.get_tqdm import get_tqdm
label_desc: Use image node_id 8 for calling a global function with example usage: eval_trainer(trainer, dev_data, batch_mode, fine_grained) and returns: dev_accuracy,  confusion_matrix,  precision_scores,  recall_scores,  f1_scores