code: def do_train(m, tq, ta, train, meta_data, args):
      """
      batch size need to be large to see all negative ans
      """
      m.train()
      for epoch in range(args.epochs):
          total_loss = 0
          start = time.time()
  
          q, ans_p, ans_n = limit_encode_train(
              train,
              meta_data["label2answer"],
              meta_data["idx2word"],
              args.q_seq_limit,
              args.ans_seq_limit,
              meta_data["idx2vec"],
          )
          bs = args.bs
  
          for i in tqdm(range(len(q) // bs)):
              tq.copy_from_numpy(q[i * bs : (i + 1) * bs])
              a_batch = np.concatenate(
                  [
                      ans_p[i * bs : (i + 1) * bs],
                      ans_n[i * bs : (i + 1) * bs],
                  ]
              )
              ta.copy_from_numpy(a_batch)
  
              p_sim, n_sim = m.forward(tq, ta)
              l = autograd.ranking_loss(p_sim, n_sim)
              m.optimizer(l)
  
              total_loss += tensor.to_numpy(l)
          print(
              "epoch %d, time used %d sec, loss: "
              % (epoch, time.time() - start),
              total_loss * bs / len(q),
          )
  
file_path: singa/examples/qabot/qabot_train.py
imports: import numpy
  import time
  import random
  from tqdm import tqdm
  import argparse
  from singa import autograd, tensor, device, opt
  from qabot_data import limit_encode_train, limit_encode_eval, prepare_data
  from qabot_model import QAModel_maxpooling
label_desc: Use image node_id 1 for calling a global function with example usage: do_train(m, tq, ta, train, meta_data, args) without return types