code: def train(
      teacher,
      student,
      train_loader,
      val_loader,
      args,
      test_pos_loader=None,
      test_neg_loader=None,
  ):
      min_err = 10000
      teacher.eval()
      student.train()
      optimizer = optim.Momentum(
          parameters=student.parameters(),
          learning_rate=args.lr,
          momentum=args.momentum,
          weight_decay=args.weight_decay,
      )
      for epoch in range(args.epochs):
          student.train()
          epoch_begin = time.time()
          end_time = time.time()
          for index, batch_data in enumerate(train_loader):
              optimizer.clear_grad()
              batch_begin = time.time()
              data_time = batch_begin - end_time
              _, batch_img = batch_data
  
              with paddle.no_grad():
                  t_feat = teacher(batch_img)
              s_feat = student(batch_img)
  
              loss = paddle.to_tensor(0.0)
              loss.stop_gradient = False
              for i in range(len(t_feat)):
                  t_feat[i] = F.normalize(t_feat[i], axis=1)
                  s_feat[i] = F.normalize(s_feat[i], axis=1)
                  loss += paddle.sum(
                      (t_feat[i] - s_feat[i]) ** 2, 1
                  ).mean()
  
              loss.backward()
              optimizer.step()
              lr = optimizer.get_lr()
              end_time = time.time()
              bacth_time = end_time - batch_begin
  
              if index % args.print_freq == 0:
                  print(
                      datetime.datetime.now().strftime(
                          "%Y-%m-%d %H:%M:%S"
                      )
                      + "\t"
                      + "Epoch {}[{}/{}]: loss:{:.5f}, lr:{:.5f}, batch time:{:.4f}, data time:{:.4f}".format(
                          epoch,
                          args.batch_size * (index + 1),
                          len(train_loader.dataset),
                          loss.cpu().numpy()[0],
                          float(lr),
                          float(bacth_time),
                          float(data_time),
                      )
                  )
          t = time.time() - epoch_begin
          print(
              datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
              + "\t"
              + "Epoch {} training ends, total {:.2f}s".format(epoch, t)
          )
          print(
              datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
              + "\t"
              + "Epoch {} testing start".format(epoch)
          )
          err = cal_error(args, teacher, student, val_loader).mean()
          print(
              datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
              + "\t"
              + "Valid Loss: {:.7f}".format(err.item())
          )
          if err < min_err:
              min_err = err
              save_name = os.path.join(
                  args.save_path, args.category, "best.pdparams"
              )
              dir_name = os.path.dirname(save_name)
              if dir_name and not os.path.exists(dir_name):
                  os.makedirs(dir_name)
              paddle.save(student.state_dict(), save_name)
          if args.do_eval:
              val(
                  args,
                  student,
                  teacher,
                  test_pos_loader,
                  test_neg_loader,
                  epoch=epoch,
                  eval_pro=args.compute_pro,
              )
          t = time.time() - epoch_begin - t
          print(
              datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
              + "\t"
              + "Epoch {} testing end, total {:.2f}s".format(epoch, t)
          )
  
imports: import os
  import sys
  import time
  import random
  import datetime
  import argparse
  from glob import glob
  import numpy
  from sklearn.model_selection import train_test_split
  import paddle
  import paddle.nn.functional
  import paddle.optimizer
  from paddle.io import DataLoader
  from paddle.vision import transforms
  from qinspector.uad.models.stfpm import ResNet_MS3
  from qinspector.uad.datasets.mvtec import MVTecDatasetSTFPM
  from qinspector.cvlib.uad_configs import ConfigParser
  from val import val, cal_error
label_desc: Use image node_id 3 for calling a global function with example usage: train(teacher, student, train_loader, val_loader, args, test_pos_loader, test_neg_loader) without return types