def __init__(self, parent=None, camera=None, data_mdl=None): QThread.__init__(self, parent=parent) print("[MLThread] Thread started..") self.camera = camera self.model = model.model() self.data = data_mdl self.mode = "none" self.cont = False self.ml_model = self.model.createModel((config.INPUT_ROW, config.INPUT_COL, config.INPUT_CH), config.OUTPUT_CLASS, config.MODEL_TYPE) self.data.setImgSize(config.WIDTH_SIZE, config.HEIGHT_SIZE, config.INPUT_CH) self.d_lbl, self.d_ind, self.d_api = self.data.importXML() self.sens_cnt = 0 self.prev_num = 0
def evaluate(eval_dataset, model, stats, opt, save = False, save_path=None, verbose = True, procrustes = False, per_joint = False, apply_dropout=False ): """ Evaluate a 2D-to-3D lifting model on a given PyTorch dataset. Adapted from ICCV 2017 baseline https://github.com/una-dinosauria/3d-pose-baseline """ num_of_joints = 14 if opt.pred14 else 17 all_dists = [] model.eval() if apply_dropout: def apply_dropout(m): if type(m) == torch.nn.Dropout: m.train() # enable the dropout layers to produce a loss similar to the training # loss (only for debugging purpose) model.apply(apply_dropout) eval_loader = torch.utils.data.DataLoader(eval_dataset, batch_size = opt.batch_size, shuffle = False, num_workers = opt.num_threads ) total_loss = 0 for batch_idx, batch in enumerate(eval_loader): data = batch[0] target = batch[1] if opt.cuda: with torch.no_grad(): data, target = data.cuda(), target.cuda() # forward pass to get prediction prediction = model(data) # mean squared loss loss = F.mse_loss(prediction, target, reduction='sum') total_loss += loss.data.item() # unnormalize the data skeleton_3d_gt = data_utils.unNormalizeData(target.data.cpu().numpy(), stats['mean_3d'], stats['std_3d'], stats['dim_ignore_3d'] ) skeleton_3d_pred = data_utils.unNormalizeData(prediction.data.cpu().numpy(), stats['mean_3d'], stats['std_3d'], stats['dim_ignore_3d'] ) # pick the joints that are used dim_use = stats['dim_use_3d'] skeleton_3d_gt_use = skeleton_3d_gt[:, dim_use] skeleton_3d_pred_use = skeleton_3d_pred[:, dim_use] # error after a regid alignment, corresponding to protocol #2 in the paper if procrustes: skeleton_3d_pred_use = align_skeleton(skeleton_3d_pred_use, skeleton_3d_gt_use, num_of_joints ) # Compute Euclidean distance error per joint sqerr = (skeleton_3d_gt_use - skeleton_3d_pred_use)**2 # Squared error between prediction and expected output dists = np.zeros((sqerr.shape[0], num_of_joints)) # Array with L2 error per joint in mm dist_idx = 0 for k in np.arange(0, num_of_joints*3, 3): # Sum across X,Y, and Z dimenstions to obtain L2 distance dists[:,dist_idx] = np.sqrt(np.sum(sqerr[:, k:k+3], axis=1)) dist_idx = dist_idx + 1 all_dists.append(dists) all_dists = np.vstack(all_dists) if per_joint: # show average error for each joint error_per_joint = all_dists.mean(axis = 0) logging.info('Average error for each joint: ') print(error_per_joint) avg_loss = total_loss/(len(eval_dataset)*16*3) if save: record = {'error':all_dists} np.save(save_path, np.array(record)) avg_distance = all_dists.mean() if verbose: logging.info('Evaluation set: average loss: {:.4f} '.format(avg_loss)) logging.info('Evaluation set: average joint distance: {:.4f} '.format(avg_distance)) return avg_loss, avg_distance
def train(train_dataset, eval_dataset, model, optim, sche, stats, action_eval_list, opt, plot_loss=False): """ Train a single deep learner. """ x_data = [] y_data = [] eval_loss, eval_distance = evaluate(eval_dataset, model, stats, opt) if plot_loss: import matplotlib.pyplot as plt # plot loss curve during training ax = plt.subplot(111) lines = ax.plot(x_data, y_data) plt.xlabel('batch') plt.ylabel('training loss') for epoch in range(1, opt.epochs + 1): model.train() # update the learning rate according to the scheduler sche.step() # data loader train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=opt.batch_size, shuffle=True, num_workers=opt.num_threads) num_batches = len(train_loader) for batch_idx, batch in enumerate(train_loader): data = batch[0] target = batch[1] if opt.cuda: with torch.no_grad(): # move to GPU data, target = data.cuda(), target.cuda() # erase all computed gradient optim.zero_grad() # forward pass to get prediction prediction = model(data) # compute loss loss = F.mse_loss(prediction, target) # smoothed l1 loss function #loss = F.smooth_l1_loss(prediction, target) # compute gradient in the computational graph loss.backward() # update parameters in the model optim.step() # logging if batch_idx % opt.report_every == 0: logger_print(epoch, batch_idx, opt.batch_size, len(train_dataset), len(train_loader), loss) x_data.append(num_batches*(epoch-1) + batch_idx) y_data.append(loss.data.item()) if plot_loss: lines[0].set_xdata(x_data) lines[0].set_ydata(y_data) ax.relim() # update ax.viewLim using the new dataLim ax.autoscale_view() plt.draw() plt.pause(0.05) # optinal evaluation if opt.eval and batch_idx!= 0 and batch_idx % opt.eval_every == 0: eval_loss, eval_distance = evaluate(eval_dataset, model, stats, opt) # update learning rate if needed #sche.step(eval_loss) # reset to training mode model.train() # evaluate after each epoch if opt.eval_action_wise and epoch % 50 == 0: evaluate_action_wise(action_eval_list, model, stats, opt) logging.info('Training finished.') return {'model':model, 'batch_idx':x_data, 'loss':y_data}