class_docstr: This is the Classification Model training class, that allows you to define a deep learning network
  from the 4 available networks types supported by ImageAI which are MobileNetv2, ResNet50,
  InceptionV3 and DenseNet121 and then train on custom image data.
class_docstr_tok: ["This","is","the","Classification","Model","training","class",",","that","allows","you","to","define","a","deep","learning","network","from","the","4","available","networks","types","supported","by","ImageAI","which","are","MobileNetv2",",","ResNet50",",","InceptionV3","and","DenseNet121","and","then","train","on","custom","image","data","."]
docstr: 'trainModel()' function starts the model actual training. It accepts the following values:
  - num_experiments: Also known as epochs, is the number of times the network will process all the images in the training dataset
  - batch_size: The number of image data that will be loaded into memory at once during training
  - model_directory: Location where json mapping and trained models will be saved
  - transfer_from_model: Path to a pre-trained imagenet model that corresponds to the training model type
  - verbose: Option to enable/disable training logs
  
  :param num_experiments:
  :param batch_size:
  :model_directory:
  :transfer_from_model:
  :verbose:
  :return:
docstr_tok: ["'trainModel","(",")","'","function","starts","the","model","actual","training",".","It","accepts","the","following","values",":","-","num_experiments",":","Also","known","as","epochs",",","is","the","number","of","times","the","network","will","process","all","the","images","in","the","training","dataset","-","batch_size",":","The","number","of","image","data","that","will","be","loaded","into","memory","at","once","during","training","-","model_directory",":","Location","where","json","mapping","and","trained","models","will","be","saved","-","transfer_from_model",":","Path","to","a","pre-trained","imagenet","model","that","corresponds","to","the","training","model","type","-","verbose",":","Option","to","enable\/disable","training","logs",":","param","num_experiments",":",":","param","batch_size",":",":","model_directory",":",":","transfer_from_model",":",":","verbose",":",":","return",":"]
code: def trainModel(
      self,
      num_experiments: int = 100,
      batch_size: int = 8,
      model_directory: str = None,
      transfer_from_model: str = None,
      verbose: bool = True,
  ) -> None:
      """
      'trainModel()' function starts the model actual training. It accepts the following values:
      - num_experiments: Also known as epochs, is the number of times the network will process all the images in the training dataset
      - batch_size: The number of image data that will be loaded into memory at once during training
      - model_directory: Location where json mapping and trained models will be saved
      - transfer_from_model: Path to a pre-trained imagenet model that corresponds to the training model type
      - verbose: Option to enable/disable training logs
  
      :param num_experiments:
      :param batch_size:
      :model_directory:
      :transfer_from_model:
      :verbose:
      :return:
      """
  
      # Load dataset
      self.__load_data(batch_size)
  
      # Check and effect transfer learning if enabled
      if transfer_from_model:
          extension_check(transfer_from_model)
          self.__model_path = transfer_from_model
  
      # Load training parameters for the specified model type
      self.__set_training_param()
  
      # Create output directory to save trained models and json mappings
      if not model_directory:
          model_directory = os.path.join(self.__data_dir, "models")
  
      if not os.path.exists(model_directory):
          os.mkdir(model_directory)
  
      # Dump class mappings to json file
      with open(
          os.path.join(
              model_directory,
              f"{self.__dataset_name}_model_classes.json",
          ),
          "w",
      ) as f:
          classes_dict = {}
          class_list = sorted(self.__class_names)
          for i in range(len(class_list)):
              classes_dict[str(i)] = class_list[i]
          json.dump(classes_dict, f)
  
      # Prep model weights for training
      since = time.time()
  
      best_model_weights = copy.deepcopy(self.__model.state_dict())
      best_acc = 0.0
      prev_save_name, recent_save_name = "", ""
  
      # Device check and log
      print("=" * 50)
      print("Training with GPU") if self.__device == "cuda" else print(
          "Training with CPU. This might cause slower train."
      )
      print("=" * 50)
  
      for epoch in range(num_experiments):
          if verbose:
              print(
                  f"Epoch {epoch + 1}/{num_experiments}",
                  "-" * 10,
                  sep="\n",
              )
  
          # each epoch has a training and test phase
          for phase in ["train", "test"]:
              if phase == "train":
                  self.__model.train()
              else:
                  self.__model.eval()
  
              running_loss = 0.0
              running_corrects = 0
  
              # Iterate on the dataset in batches
              for imgs, labels in tqdm(self.__data_loaders[phase]):
                  imgs = imgs.to(self.__device)
                  labels = labels.to(self.__device)
  
                  self.__optimizer.zero_grad()
  
                  with torch.set_grad_enabled(phase == "train"):
                      output = self.__model(imgs)
                      if (
                          self.__model_type == "inception_v3"
                          and type(output) == InceptionOutputs
                      ):
                          output = output[0]
                      _, preds = torch.max(output, 1)
                      loss = self.__loss_fn(output, labels)
  
                      if phase == "train":
                          loss.backward()
                          self.__optimizer.step()
                  running_loss += loss.item() * imgs.size(0)
                  running_corrects += torch.sum(preds == labels.data)
  
              # Compute accuracy and loss metrics post epoch training
              if phase == "train" and isinstance(
                  self.__lr_scheduler, torch.optim.lr_scheduler.StepLR
              ):
                  self.__lr_scheduler.step()
  
              epoch_loss = running_loss / self.__dataset_sizes[phase]
              epoch_acc = (
                  running_corrects.double()
                  / self.__dataset_sizes[phase]
              )
  
              if verbose:
                  print(
                      f"{phase} Loss: {epoch_loss:.4f} Accuracy: {epoch_acc:.4f}"
                  )
              if phase == "test" and epoch_acc > best_acc:
                  best_acc = epoch_acc
                  recent_save_name = (
                      self.__model_type
                      + f"-{self.__dataset_name}-test_acc_{best_acc:.5f}_epoch-{epoch}.pt"
                  )
                  if prev_save_name:
                      os.remove(
                          os.path.join(model_directory, prev_save_name)
                      )
                  best_model_weights = copy.deepcopy(
                      self.__model.state_dict()
                  )
                  torch.save(
                      best_model_weights,
                      os.path.join(model_directory, recent_save_name),
                  )
                  prev_save_name = recent_save_name
  
      time_elapsed = time.time() - since
      print(
          f"Training completed in {time_elapsed//60:.0f}m {time_elapsed % 60:.0f}s"
      )
      print(f"Best test accuracy: {best_acc:.4f}")
  
imports: import time, warnings
  import os
  import copy
  import re
  import json
  from typing import List, Tuple, Union
  from PIL import Image
  import numpy
  import torch
  import torch.nn
  from torch.optim import lr_scheduler
  from torchvision import datasets
  from torchvision import transforms
  from torchvision.models import mobilenet_v2, inception_v3, resnet50, densenet121
  from torchvision.models.inception import InceptionOutputs
  from .data_transformation import data_transforms1, data_transforms2
  from .training_params import resnet50_train_params, densenet121_train_params, inception_v3_train_params, mobilenet_v2_train_params
  from tqdm import tqdm
  from ...backend_check.model_extension import extension_check
label_desc: Use image node_id 12 for calling the ClassificationModelTrainer obj's underlying member method code with example usage: obj.trainModel(num_experiments, batch_size, model_directory, transfer_from_model, verbose) without return types