class_docstr: Implementation of assisted Knowledge distillation from the paper "Improved Knowledge
  Distillation via Teacher Assistant" https://arxiv.org/pdf/1902.03393.pdf
  
  :param teacher_model (torch.nn.Module): Teacher model
  :param assistant_models (list or tuple): Assistant models
  :param student_model (torch.nn.Module): Student model
  :param assistant_train_order (list or tuple or array): Order of training for that assistant
  :param train_loader (torch.utils.data.DataLoader): Dataloader for training
  :param val_loader (torch.utils.data.DataLoader): Dataloader for validation/testing
  :param optimizer_teacher (torch.optim.*): Optimizer used for training teacher
  :param optimizer_assistants (torch.optim.*): Optimizer used for training assistants
  :param optimizer_student (torch.optim.*): Optimizer used for training student
  :param loss_fn (torch.nn.Module):  Calculates loss during distillation
  :param temp (float): Temperature parameter for distillation
  :param distil_weight (float): Weight paramter for distillation loss
  :param device (str): Device used for training; 'cpu' for cpu and 'cuda' for gpu
  :param log (bool): True if logging required
  :param logdir (str): Directory for storing logs
class_docstr_tok: ["Implementation","of","assisted","Knowledge","distillation","from","the","paper","``","Improved","Knowledge","Distillation","via","Teacher","Assistant","''","https",":","\/\/arxiv.org\/pdf\/1902.03393.pdf",":","param","teacher_model","(","torch.nn.Module",")",":","Teacher","model",":","param","assistant_models","(","list","or","tuple",")",":","Assistant","models",":","param","student_model","(","torch.nn.Module",")",":","Student","model",":","param","assistant_train_order","(","list","or","tuple","or","array",")",":","Order","of","training","for","that","assistant",":","param","train_loader","(","torch.utils.data.DataLoader",")",":","Dataloader","for","training",":","param","val_loader","(","torch.utils.data.DataLoader",")",":","Dataloader","for","validation\/testing",":","param","optimizer_teacher","(","torch.optim",".","*",")",":","Optimizer","used","for","training","teacher",":","param","optimizer_assistants","(","torch.optim",".","*",")",":","Optimizer","used","for","training","assistants",":","param","optimizer_student","(","torch.optim",".","*",")",":","Optimizer","used","for","training","student",":","param","loss_fn","(","torch.nn.Module",")",":","Calculates","loss","during","distillation",":","param","temp","(","float",")",":","Temperature","parameter","for","distillation",":","param","distil_weight","(","float",")",":","Weight","paramter","for","distillation","loss",":","param","device","(","str",")",":","Device","used","for","training",";","'cpu","'","for","cpu","and","'cuda","'","for","gpu",":","param","log","(","bool",")",":","True","if","logging","required",":","param","logdir","(","str",")",":","Directory","for","storing","logs"]
docstr: Function used for distillation
  
  :param teachers (list or tuple): Teachers used for distillation
  :param model (nn.Module): Model learning during distillation
  :param optimizer (torch.optim.*): Optimizer used for training
  :param epochs (int): Number of epochs to train
  :param plot_losses (bool): True if the loss curves need to be plotted
  :param save_model (bool): True if the model needs to be saved
  :param save_model_path (str): Path used for storing the model
docstr_tok: ["Function","used","for","distillation",":","param","teachers","(","list","or","tuple",")",":","Teachers","used","for","distillation",":","param","model","(","nn.Module",")",":","Model","learning","during","distillation",":","param","optimizer","(","torch.optim",".","*",")",":","Optimizer","used","for","training",":","param","epochs","(","int",")",":","Number","of","epochs","to","train",":","param","plot_losses","(","bool",")",":","True","if","the","loss","curves","need","to","be","plotted",":","param","save_model","(","bool",")",":","True","if","the","model","needs","to","be","saved",":","param","save_model_path","(","str",")",":","Path","used","for","storing","the","model"]
code: def train_distil_model(
      self,
      teachers,
      model,
      optimizer,
      epochs=20,
      plot_losses=True,
      save_model=True,
      save_model_pth="./models/student.pt",
  ):
      """
      Function used for distillation
  
      :param teachers (list or tuple): Teachers used for distillation
      :param model (nn.Module): Model learning during distillation
      :param optimizer (torch.optim.*): Optimizer used for training
      :param epochs (int): Number of epochs to train
      :param plot_losses (bool): True if the loss curves need to be plotted
      :param save_model (bool): True if the model needs to be saved
      :param save_model_path (str): Path used for storing the model
      """
  
      model.train()
      length_of_dataset = len(self.train_loader.dataset)
      best_acc = 0.0
      self.best_model_weights = deepcopy(model.state_dict())
  
      if not isinstance(teachers, list):
          teachers = [teachers]
  
      for epoch in range(epochs):
          correct = 0
          epoch_loss = 0.0
          for _, (data, target) in enumerate(self.train_loader):
              data = data.to(self.device)
              target = target.to(self.device)
  
              scores = model(data)
  
              pred = scores.argmax(dim=1, keepdim=True)
              correct += pred.eq(target.view_as(pred)).sum().item()
  
              teacher_output = teachers[0](data)
              for i in range(1, len(teachers)):
                  teacher_output += teachers[i](data)
              teacher_output /= len(teachers)
  
              loss = self.calculate_kd_loss(
                  scores, teacher_output, target
              )
  
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
  
              epoch_loss += loss.item()
  
          epoch_acc = correct / length_of_dataset
  
          _, epoch_val_acc = self._evaluate_model(model)
  
          if epoch_val_acc > best_acc:
              best_acc = epoch_val_acc
              self.best_model_weights = deepcopy(model.state_dict())
  
          print(
              f"Epoch: {epoch}, Loss: {epoch_loss}, Accuracy: {epoch_acc}"
          )
  
      model.load_state_dict(self.best_model_weights)
      if save_model:
          torch.save(model.state_dict(), save_model_pth)
  
file_path: KD_Lib/KD_Lib/KD/vision/TAKD/takd.py
imports: from copy import deepcopy
  import matplotlib.pyplot
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.optim
  from KD_Lib.KD.common import BaseClass
label_desc: Use image node_id 3 for calling the TAKD obj's underlying member method code with example usage: obj.train_distil_model(teachers, model, optimizer, epochs, plot_losses, save_model, save_model_pth) without return types