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.
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","."]
docstr: 'trainModel()' function starts the model actual training. It accepts the following values:
  - num_objects , which is the number of classes present in the dataset that is to be used for training
  - num_experiments , also known as epochs, it is the number of times the network will train on all the training dataset
  - enhance_data (optional) , this is used to modify the dataset and create more instance of the training set to enhance the training result
  - batch_size (optional) , due to memory constraints, the network trains on a batch at once, until all the training set is exhausted. The value is set to 32 by default, but can be increased or decreased depending on the meormory of the compute used for training. The batch_size is conventionally set to 16, 32, 64, 128.
  - initial_learning_rate(optional) , this value is used to adjust the weights generated in the network. You rae advised to keep this value as it is if you don't have deep understanding of this concept.
  - show_network_summary(optional) , this value is used to show the structure of the network should you desire to see it. It is set to False by default
  - training_image_size(optional) , this value is used to define the image size on which the model will be trained. The value is 224 by default and is kept at a minimum of 100.
  - continue_from_model (optional) , this is used to set the path to a model file trained on the same dataset. It is primarily for continuos training from a previously saved model.
  - transfer_from_model (optional) , this is used to set the path to a model file trained on another dataset. It is primarily used to perform tramsfer learning.
  - transfer_with_full_training (optional) , this is used to set the pre-trained model to be re-trained across all the layers or only at the top layers.
  - initial_num_objects (required if 'transfer_from_model' is set ), this is used to set the number of objects the model used for transfer learning is trained on. If 'transfer_from_model' is set, this must be set as well.
  - save_full_model ( optional ), this is used to save the trained models with their network types. Any model saved by this specification can be loaded without specifying the network type.
  
  
  :param num_objects:
  :param num_experiments:
  :param enhance_data:
  :param batch_size:
  :param initial_learning_rate:
  :param show_network_summary:
  :param training_image_size:
  :param continue_from_model:
  :param transfer_from_model:
  :param initial_num_objects:
  :param save_full_model:
  :return:
docstr_tok: ["'trainModel","(",")","'","function","starts","the","model","actual","training",".","It","accepts","the","following","values",":","-","num_objects",",","which","is","the","number","of","classes","present","in","the","dataset","that","is","to","be","used","for","training","-","num_experiments",",","also","known","as","epochs",",","it","is","the","number","of","times","the","network","will","train","on","all","the","training","dataset","-","enhance_data","(","optional",")",",","this","is","used","to","modify","the","dataset","and","create","more","instance","of","the","training","set","to","enhance","the","training","result","-","batch_size","(","optional",")",",","due","to","memory","constraints",",","the","network","trains","on","a","batch","at","once",",","until","all","the","training","set","is","exhausted",".","The","value","is","set","to","32","by","default",",","but","can","be","increased","or","decreased","depending","on","the","meormory","of","the","compute","used","for","training",".","The","batch_size","is","conventionally","set","to","16",",","32",",","64",",","128",".","-","initial_learning_rate","(","optional",")",",","this","value","is","used","to","adjust","the","weights","generated","in","the","network",".","You","rae","advised","to","keep","this","value","as","it","is","if","you","do","n't","have","deep","understanding","of","this","concept",".","-","show_network_summary","(","optional",")",",","this","value","is","used","to","show","the","structure","of","the","network","should","you","desire","to","see","it",".","It","is","set","to","False","by","default","-","training_image_size","(","optional",")",",","this","value","is","used","to","define","the","image","size","on","which","the","model","will","be","trained",".","The","value","is","224","by","default","and","is","kept","at","a","minimum","of","100",".","-","continue_from_model","(","optional",")",",","this","is","used","to","set","the","path","to","a","model","file","trained","on","the","same","dataset",".","It","is","primarily","for","continuos","training","from","a","previously","saved","model",".","-","transfer_from_model","(","optional",")",",","this","is","used","to","set","the","path","to","a","model","file","trained","on","another","dataset",".","It","is","primarily","used","to","perform","tramsfer","learning",".","-","transfer_with_full_training","(","optional",")",",","this","is","used","to","set","the","pre-trained","model","to","be","re-trained","across","all","the","layers","or","only","at","the","top","layers",".","-","initial_num_objects","(","required","if","'transfer_from_model","'","is","set",")",",","this","is","used","to","set","the","number","of","objects","the","model","used","for","transfer","learning","is","trained","on",".","If","'transfer_from_model","'","is","set",",","this","must","be","set","as","well",".","-","save_full_model","(","optional",")",",","this","is","used","to","save","the","trained","models","with","their","network","types",".","Any","model","saved","by","this","specification","can","be","loaded","without","specifying","the","network","type",".",":","param","num_objects",":",":","param","num_experiments",":",":","param","enhance_data",":",":","param","batch_size",":",":","param","initial_learning_rate",":",":","param","show_network_summary",":",":","param","training_image_size",":",":","param","continue_from_model",":",":","param","transfer_from_model",":",":","param","initial_num_objects",":",":","param","save_full_model",":",":","return",":"]
code: def trainModel(
      self,
      num_objects,
      num_experiments=200,
      enhance_data=False,
      batch_size=32,
      initial_learning_rate=1e-3,
      show_network_summary=False,
      training_image_size=224,
      continue_from_model=None,
      transfer_from_model=None,
      transfer_with_full_training=True,
      initial_num_objects=None,
      save_full_model=False,
  ):
      """
      'trainModel()' function starts the model actual training. It accepts the following values:
      - num_objects , which is the number of classes present in the dataset that is to be used for training
      - num_experiments , also known as epochs, it is the number of times the network will train on all the training dataset
      - enhance_data (optional) , this is used to modify the dataset and create more instance of the training set to enhance the training result
      - batch_size (optional) , due to memory constraints, the network trains on a batch at once, until all the training set is exhausted. The value is set to 32 by default, but can be increased or decreased depending on the meormory of the compute used for training. The batch_size is conventionally set to 16, 32, 64, 128.
      - initial_learning_rate(optional) , this value is used to adjust the weights generated in the network. You rae advised to keep this value as it is if you don't have deep understanding of this concept.
      - show_network_summary(optional) , this value is used to show the structure of the network should you desire to see it. It is set to False by default
      - training_image_size(optional) , this value is used to define the image size on which the model will be trained. The value is 224 by default and is kept at a minimum of 100.
      - continue_from_model (optional) , this is used to set the path to a model file trained on the same dataset. It is primarily for continuos training from a previously saved model.
      - transfer_from_model (optional) , this is used to set the path to a model file trained on another dataset. It is primarily used to perform tramsfer learning.
      - transfer_with_full_training (optional) , this is used to set the pre-trained model to be re-trained across all the layers or only at the top layers.
      - initial_num_objects (required if 'transfer_from_model' is set ), this is used to set the number of objects the model used for transfer learning is trained on. If 'transfer_from_model' is set, this must be set as well.
      - save_full_model ( optional ), this is used to save the trained models with their network types. Any model saved by this specification can be loaded without specifying the network type.
  
  
      :param num_objects:
      :param num_experiments:
      :param enhance_data:
      :param batch_size:
      :param initial_learning_rate:
      :param show_network_summary:
      :param training_image_size:
      :param continue_from_model:
      :param transfer_from_model:
      :param initial_num_objects:
      :param save_full_model:
      :return:
      """
      self.__num_epochs = num_experiments
      self.__initial_learning_rate = initial_learning_rate
      lr_scheduler = tf.keras.callbacks.LearningRateScheduler(
          self.lr_schedule
      )
  
      if training_image_size < 100:
          warnings.warn(
              "The specified training_image_size {} is less than 100. Hence the training_image_size will default to 100.".format(
                  training_image_size
              )
          )
          training_image_size = 100
  
      if self.__modelType == "mobilenetv2":
          if continue_from_model != None:
              model = tf.keras.applications.MobileNetV2(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=continue_from_model,
                  classes=num_objects,
                  include_top=True,
              )
              if show_network_summary == True:
                  print("Training using weights from a previouly model")
          elif transfer_from_model != None:
              base_model = tf.keras.applications.MobileNetV2(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=transfer_from_model,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.model.Models(
                  inputs=base_model.input, outputs=network
              )
  
              if show_network_summary == True:
                  print(
                      "Training using weights from a pre-trained ImageNet model"
                  )
          else:
              base_model = tf.keras.applications.MobileNetV2(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=None,
                  classes=num_objects,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.models.Model(
                  inputs=base_model.input, outputs=network
              )
  
      elif self.__modelType == "resnet50":
          if continue_from_model != None:
              model = tf.keras.applications.ResNet50(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=continue_from_model,
                  classes=num_objects,
                  include_top=True,
              )
              if show_network_summary == True:
                  print("Training using weights from a previouly model")
          elif transfer_from_model != None:
              base_model = tf.keras.applications.ResNet50(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=transfer_from_model,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.model.Models(
                  inputs=base_model.input, outputs=network
              )
  
              if show_network_summary == True:
                  print(
                      "Training using weights from a pre-trained ImageNet model"
                  )
          else:
              base_model = tf.keras.applications.ResNet50(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=None,
                  classes=num_objects,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.models.Model(
                  inputs=base_model.input, outputs=network
              )
  
      elif self.__modelType == "inceptionv3":
          if continue_from_model != None:
              model = tf.keras.applications.InceptionV3(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=continue_from_model,
                  classes=num_objects,
                  include_top=True,
              )
              if show_network_summary == True:
                  print("Training using weights from a previouly model")
          elif transfer_from_model != None:
              base_model = tf.keras.applications.InceptionV3(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=transfer_from_model,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.model.Models(
                  inputs=base_model.input, outputs=network
              )
  
              if show_network_summary == True:
                  print(
                      "Training using weights from a pre-trained ImageNet model"
                  )
          else:
              base_model = tf.keras.applications.InceptionV3(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=None,
                  classes=num_objects,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.models.Model(
                  inputs=base_model.input, outputs=network
              )
  
          base_model = tf.keras.applications.InceptionV3(
              input_shape=(training_image_size, training_image_size, 3),
              weights=None,
              classes=num_objects,
              include_top=False,
              pooling="avg",
          )
  
      elif self.__modelType == "densenet121":
          if continue_from_model != None:
              model = tf.keras.applications.DenseNet121(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=continue_from_model,
                  classes=num_objects,
                  include_top=True,
              )
              if show_network_summary == True:
                  print("Training using weights from a previouly model")
          elif transfer_from_model != None:
              base_model = tf.keras.applications.DenseNet121(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=transfer_from_model,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.model.Models(
                  inputs=base_model.input, outputs=network
              )
  
              if show_network_summary == True:
                  print(
                      "Training using weights from a pre-trained ImageNet model"
                  )
          else:
              base_model = tf.keras.applications.DenseNet121(
                  input_shape=(
                      training_image_size,
                      training_image_size,
                      3,
                  ),
                  weights=None,
                  classes=num_objects,
                  include_top=False,
                  pooling="avg",
              )
  
              network = base_model.output
              network = tf.keras.layers.Dense(
                  num_objects, activation="softmax", use_bias=True
              )(network)
  
              model = tf.keras.models.Model(
                  inputs=base_model.input, outputs=network
              )
  
          base_model = tf.keras.applications.DenseNet121(
              input_shape=(training_image_size, training_image_size, 3),
              weights=None,
              classes=num_objects,
              include_top=False,
              pooling="avg",
          )
  
      optimizer = tf.keras.optimizers.Adam(
          lr=self.__initial_learning_rate, decay=1e-4
      )
      model.compile(
          loss="categorical_crossentropy",
          optimizer=optimizer,
          metrics=["accuracy"],
      )
      if show_network_summary == True:
          model.summary()
  
      model_name = "model_ex-{epoch:03d}_acc-{accuracy:03f}.h5"
  
      log_name = "{}_lr-{}_{}".format(
          self.__modelType,
          initial_learning_rate,
          time.strftime("%Y-%m-%d-%H-%M-%S"),
      )
  
      if not os.path.isdir(self.__trained_model_dir):
          os.makedirs(self.__trained_model_dir)
  
      if not os.path.isdir(self.__model_class_dir):
          os.makedirs(self.__model_class_dir)
  
      if not os.path.isdir(self.__logs_dir):
          os.makedirs(self.__logs_dir)
  
      model_path = os.path.join(self.__trained_model_dir, model_name)
  
      logs_path = os.path.join(self.__logs_dir, log_name)
      if not os.path.isdir(logs_path):
          os.makedirs(logs_path)
  
      save_weights_condition = True
  
      if save_full_model == True:
          save_weights_condition = False
  
      checkpoint = tf.keras.callbacks.ModelCheckpoint(
          filepath=model_path,
          monitor="accuracy",
          verbose=1,
          save_weights_only=save_weights_condition,
          save_best_only=True,
          period=1,
      )
  
      tensorboard = tf.keras.callbacks.TensorBoard(
          log_dir=logs_path,
          histogram_freq=0,
          write_graph=False,
          write_images=False,
      )
  
      if enhance_data == True:
          print("Using Enhanced Data Generation")
  
      height_shift = 0
      width_shift = 0
      if enhance_data == True:
          height_shift = 0.1
          width_shift = 0.1
  
      train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
          rescale=1.0 / 255,
          horizontal_flip=enhance_data,
          height_shift_range=height_shift,
          width_shift_range=width_shift,
      )
  
      test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
          rescale=1.0 / 255
      )
  
      train_generator = train_datagen.flow_from_directory(
          self.__train_dir,
          target_size=(training_image_size, training_image_size),
          batch_size=batch_size,
          class_mode="categorical",
      )
      test_generator = test_datagen.flow_from_directory(
          self.__test_dir,
          target_size=(training_image_size, training_image_size),
          batch_size=batch_size,
          class_mode="categorical",
      )
  
      class_indices = train_generator.class_indices
      class_json = {}
      for eachClass in class_indices:
          class_json[str(class_indices[eachClass])] = eachClass
  
      with open(
          os.path.join(self.__model_class_dir, "model_class.json"), "w+"
      ) as json_file:
          json.dump(
              class_json,
              json_file,
              indent=4,
              separators=(",", " : "),
              ensure_ascii=True,
          )
          json_file.close()
      print(
          "JSON Mapping for the model classes saved to ",
          os.path.join(self.__model_class_dir, "model_class.json"),
      )
  
      num_train = len(train_generator.filenames)
      num_test = len(test_generator.filenames)
      print("Number of experiments (Epochs) : ", self.__num_epochs)
  
      model.fit_generator(
          train_generator,
          steps_per_epoch=int(num_train / batch_size),
          epochs=self.__num_epochs,
          validation_data=test_generator,
          validation_steps=int(num_test / batch_size),
          callbacks=[checkpoint, lr_scheduler],
      )
  
imports: import tensorflow
  from PIL import Image
  import time
  import numpy
  import os
  import warnings
  from matplotlib.cbook import deprecated
  import json
label_desc: Use image node_id 11 for calling the ClassificationModelTrainer obj's underlying member method code with example usage: obj.trainModel(num_objects, num_experiments, enhance_data, batch_size, initial_learning_rate, show_network_summary, training_image_size, continue_from_model, transfer_from_model, transfer_with_full_training, initial_num_objects, save_full_model) without return types