def zsl_acc(semantic_predicted, semantic_gt, opts): # zsl_acc calculates zero-shot classification accruacy # # INPUTS: # semantic_prediced: predicted semantic labels # semantic_gt: ground truth semantic labels # opts: other parameters # # OUTPUT: # zsl_accuracy: zero-shot classification accuracy (per-sample) pre_label = [] dist = 1 - distCosine( semantic_predicted, normalizeFeature(semantic_gt.transpose()).transpose()) y_hit_k = np.zeros((dist.shape[0], opts.HITK)) for idx in range(0, dist.shape[0]): sorted_id = sorted(range(len(dist[idx, :])), key=lambda k: dist[idx, :][k], reverse=True) y_hit_k[idx, :] = opts.test_classes_id[sorted_id[0:opts.HITK]] n = 0 true_label = opts.test_labels.tolist() true_label = [int(i) for i in true_label] # for idx in range(0, dist.shape[0]): # if opts.test_labels[idx] in y_hit_k[idx,:]: # n = n + 1 # zsl_accuracy = float(n) / dist.shape[0] * 100 # return zsl_accuracy, y_hit_k for idx in range(0, dist.shape[0]): if opts.test_labels[idx] in y_hit_k[idx, :]: pre_label.append(int(true_label[idx])) else: pre_label.append(int(y_hit_k[idx, 0])) zsl_accuracy = macro_acc(true_label, pre_label) return zsl_accuracy * 100, y_hit_k
def dtest(te, model, combine_dir, devce, loss_fn=nn.MSELoss()): # get vec mat vec_mat = get_vec_mat() pth = combine_dir dirs_general = os.listdir(pth) vec_m_combine = [] # unseen 训练集的矩阵 ids_combine = [] for f in dirs_general: # 对于seen和unseen类 id = int(re.sub("\D", "", f)) ids_combine.append(id) idx = id - 1 vec_m_combine.append(vec_mat[idx]) vec_m_combine = np.array(vec_m_combine) #print("size of vec test mat :", vec_m_combine.shape) # 49+19=68,500 print('test begin:') vec_m_combine = vec_m_combine.transpose() with torch.no_grad(): model.eval() real_label_test = [] pre_label_test_1 = [] pre_label_test_2 = [] # hit 2 pre_label_test_5 = [] # hit 5 loss_total_test = 0 for (vx, vy) in te: val_vec_y, val_tag_y = vy val_vec_y = val_vec_y.to(devce, dtype=torch.float) vx = vx.to(devce, dtype=torch.float) vy_pred = model(vx) vloss = loss_fn(vy_pred, val_vec_y) # test set loss compute loss_total_test += vloss.item() ### pre whether correct? ### # real_label_test.extend(val_tag_y) # vy_pred_cpu = vy_pred.cpu().detach().numpy() vsz = len(val_tag_y) vtt = np.dot(vy_pred_cpu, vec_m_combine) # judge by dot Multiplication for n in range(vsz): e = heapq.nlargest(5, range(len(vtt[n])), vtt[n].take) # top 5 hit vi = 0 while vi < 5: if (ids_combine[e[vi]] == val_tag_y[n]): # pre right break vi += 1 pre_label_test_1.append(ids_combine[e[0]]) pre_label_test_2.append(ids_combine[e[0]]) pre_label_test_5.append(ids_combine[e[0]]) if (vi <= 1): pre_label_test_2[-1] = val_tag_y[n] pre_label_test_5[-1] = val_tag_y[n] elif (vi <= 4): pre_label_test_5[-1] = val_tag_y[n] acc_test_1 = macro_acc(real_label_test, pre_label_test_1) acc_test_2 = macro_acc(real_label_test, pre_label_test_2) acc_test_5 = macro_acc(real_label_test, pre_label_test_5) print( 'test macro_acc_1: {:04.2f}% macro_acc_2: {:04.2f}% macro_acc_5: {:04.2f}%' .format(acc_test_1 * 100, acc_test_2 * 100, acc_test_5 * 100)) return acc_test_1, acc_test_2, acc_test_5, loss_total_test
def train(core_model, folder_dir_train, folder_dir_eval, loss_fn): output_folder = './save_model' os.makedirs(output_folder, exist_ok=True) # load training data tr_img = data_reader(folder_dir_train) tr = DataLoader(tr_img, batch_size=batch_size, shuffle=True, num_workers=8) optimizer_tag = optim.Adam(core_model.parameters(), lr=lr, weight_decay=wds) print('using {} as criterion'.format(loss_fn)) # load testing data te_img = data_reader(folder_dir_eval) # test te = DataLoader(te_img, batch_size=50, num_workers=8) # test # get semantic embedding from .mat file (i.e., training labels) vec_mat = get_vec_mat() pth = folder_dir_train dirs_seen = os.listdir(pth) pth = folder_dir_eval vec_m = [] # seen matrix for training set ids = [] # id of 25 seen classes for f in dirs_seen: # data of seen class id = int(re.sub("\D", "", f)) ids.append(id) idx = id - 1 vec_m.append(vec_mat[idx]) vec_m = np.array(vec_m) print("size of seen semantic embedding:", vec_m.shape) # (25,500) vec_m = vec_m.transpose() # hit @ 1, 2, 5 best_acc_te_1, best_acc_te_2, best_acc_te_5 = 0, 0, 0 writer = SummaryWriter() # training and testing, select the better result to save or save every 10 epochs for epoch in range(epoch_num): core_model.train() loss_total = 0 real_label = [] pre_label_1 = [] pre_label_2 = [] # hit 2 pre_label_5 = [] # hit 5 print('train begin:') for i, (x, y) in enumerate(tr, 1): vec_y, tag_y = y # vec tag x = x.to(GPU, dtype=torch.float) vec_y = vec_y.to(GPU, dtype=torch.float) core_model.zero_grad() # print(type(x)) y_pred = core_model(x) loss = loss_fn(y_pred, vec_y) loss.backward() optimizer_tag.step() ### pre whether correct? ### # real_label.extend(tag_y) # batch_size # sz = len(tag_y) y_pred_cpu = y_pred.cpu().detach().numpy() tt = np.dot(y_pred_cpu, vec_m) # judge by dot Multiplication for n in range(sz): e = heapq.nlargest(5, range(len(tt[n])), tt[n].take) ii = 0 while ii < 5: if (ids[e[ii]] == tag_y[n]): break ii += 1 pre_label_1.append(ids[e[0]]) pre_label_2.append(ids[e[0]]) pre_label_5.append(ids[e[0]]) if (ii <= 1): pre_label_2[-1] = tag_y[n] pre_label_5[-1] = tag_y[n] elif (ii <= 4): pre_label_5[-1] = tag_y[n] loss_total += loss.item() acc_1 = macro_acc(real_label, pre_label_1) # hit 1 acc_2 = macro_acc(real_label, pre_label_2) # hit 2 acc_5 = macro_acc(real_label, pre_label_5) # hit 5 print( 'Epoch {:4d}/{:4d} total_loss:{:06.5f} macro_acc_1: {:04.2f}% macro_acc_2: {:04.2f}% macro_acc_5: {:04.2f}%' .format(epoch, epoch_num, loss_total, acc_1 * 100, acc_2 * 100, acc_5 * 100)) #print('total time: {:>5.2f}s'.format(time.time() - epoch_st)) writer.add_scalars('macro_acc', { 'hit_1': acc_1, 'hit_2': acc_2, 'hit_5': acc_5 }, epoch) writer.add_scalar('loss', loss_total, epoch) # testing Generalized ZSL combine_dir = "./ZSL_DATA/test_2/combine" acc_test_1, acc_test_2, acc_test_5, loss_total_test = DeVise_test_GZSL.dtest( te, core_model, combine_dir, GPU, loss_fn) #print( # 'test macro_prec_1: {:04.2f}% macro_acc_2: {:04.2f}% macro_acc_5: {:04.2f}%'.format(acc_test_1 * 100, # acc_test_2 * 100, # acc_test_5 * 100)) writer.add_scalars('test macro_acc', { 'hit_1': acc_test_1, 'hit_2': acc_test_2, 'hit_5': acc_test_5 }, epoch) writer.add_scalar('test loss', loss_total_test, epoch) if epoch > 5 and (acc_test_1 > best_acc_te_1 or acc_test_2 > best_acc_te_2 or acc_test_5 > best_acc_te_5): ans = "_" if acc_test_1 > best_acc_te_1: best_acc_te_1 = acc_test_1 ans += "hit1_" ans += str(acc_test_1 * 100)[:5] ans += "%" if acc_test_2 > best_acc_te_2: best_acc_te_2 = acc_test_2 ans += "hit2_" ans += str(acc_test_2 * 100)[:5] ans += "%" if acc_test_5 > best_acc_te_5: best_acc_te_5 = acc_test_5 ans += "hit5_" ans += str(acc_test_5 * 100)[:5] ans += "%" # './save_model' torch.save( core_model.state_dict(), os.path.join( output_folder, str(round(time.time())) + 'epoch' + str(epoch) + ans + '.pkl')) # each 10 epoch save elif (epoch > 0 and epoch % 10 == 0): torch.save( core_model.state_dict(), os.path.join( output_folder, str(round(time.time())) + 'epoch' + str(epoch) + '.pkl')) writer.close() print("best_acc_te_1:", best_acc_te_1) print("best_acc_te_2:", best_acc_te_2) print("best_acc_te_5:", best_acc_te_5)