def obj(args): P0 = P.copy() P0.update(args) P0.log("Check Params: "+", ".join([str(key)+' = '+ ("'"+val+"'" if isinstance(val,str) else str(val)) for key,val in args.items()]),name='hyperopt') perf_mat_C = np.empty(shape=(2,P.get('runs'),len(DL_V))) perf_mat_D = np.empty(shape=(3,P.get('runs'))) for run in range(P0.get('runs')): G, D, C, _, _ = GAN.train_GAN(P0, DL_L, DL_U_iter, DL_V, name=P0.get('name')+'_%d'%run) G.eval();D.eval();C.eval(); with torch.no_grad(): acc_D = np.empty(shape=(2,len(DL_V))) for i,(XV, YV) in enumerate(DL_V): YC = C(XV) perf_mat_C[0,run,i] = calc_f1score(YC, YV, average = 'weighted') perf_mat_C[1,run,i] = calc_accuracy(YC, YV) acc_D[0,i] = calc_accuracy(D(torch.cat((XV,YV),dim=1)),floatTensor(XV.shape[0],1).fill_(1.0)) acc_D[1,i] = calc_accuracy(D(torch.cat((XV,YC),dim=1)),floatTensor(XV.shape[0],1).fill_(0.0)) YV = floatTensor(pp.get_one_hot_labels(P0,num=P0.get('batch_size'))) perf_mat_D[0,run] = calc_accuracy(D(torch.cat((G(torch.cat((floatTensor(np.random.normal(0,1,(P0.get('batch_size'),P0.get('noise_shape')))),YV),dim=1)),YV),dim=1)),floatTensor(P0.get('batch_size'),1).fill_(0.0)) perf_mat_D[1,run] = np.mean(acc_D[0]) perf_mat_D[2,run] = np.mean(acc_D[1]) perf = np.mean(perf_mat_C.reshape(2,-1),axis=1) val = ( 0.15 * np.mean((0.5-perf_mat_D[0])**2) # G/D acc ideally is around 50% + 0.05 * np.mean((1-perf_mat_D[1])**2) # D is rewarded for accurately classifying real pairs + 0.05 * np.mean((1-perf_mat_D[2])**2) # D is rewarded for accurately classifying classifier predictions - perf[0] # C F1 score is most important ) P0.log(f"loss = {val:.5f} [Accuracy D = {np.mean(perf_mat_D):.5f} | vs G = {np.mean(perf_mat_D[0]):.5f} | vs C = {np.mean(perf_mat_D[2]):.5f} | vs real = {np.mean(perf_mat_D[1]):.5f}] [C - F1: {perf[0]:.5f} | Accuracy: {perf[1]:.5f}]",name='hyperopt') return val
def train_Base(P, DL_L, DL_V, name=None): name = name if name is not None else P.get('name') R_Loss = network.CrossEntropyLoss_OneHot() if P.get('CUDA') and torch.cuda.is_available(): R_Loss.cuda() mat_accuracy = np.zeros((1, int(P.get('epochs') / P.get('save_step')) + 1)) mat_f1_score = np.zeros((1, int(P.get('epochs') / P.get('save_step')) + 1)) R = network.load_R(P) optimizer_R = network.get_optimiser(P, 'C', R.parameters()) for epoch in range(P.get('epochs_GD'), P.get('epochs')): R.train() for i, (X1, Y1) in enumerate(DL_L, 1): optimizer_R.zero_grad() PR = R(X1) loss = R_Loss(PR, Y1) loss.backward() optimizer_R.step() if (epoch + 1) % P.get('save_step') == 0: idx = int(epoch / P.get('save_step')) + 1 R.eval() with torch.no_grad(): mat1, mat2 = [], [] for XV, YV in DL_V: mat1.append(calc_accuracy(R(XV), YV)) mat2.append(calc_f1score(R(XV), YV, average='macro')) mat_accuracy[0, idx] = np.mean(mat1) mat_f1_score[0, idx] = np.mean(mat2) return R, mat_accuracy, mat_f1_score
def main_test(dataset): """ Predictor Test """ tf.reset_default_graph() lr = logistic_regressor.LogisticRegressor(feature_num=conf.FEATURE_NUM, learning_rate=conf.LEARNING_RATE, random_seed=None) saver, logits, loss, train_op, stat_merged = lr.build_graph() with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) saver.restore(sess, '{}/model'.format(conf.CHKPT_DIR)) in_feature_vecs = dataset[0][:100] in_labels = dataset[1][:100] in_labels = np.expand_dims(in_labels, 1) feed_dict = { lr.input_feature_vectors: in_feature_vecs, lr.input_labels: in_labels } out_logits, out_weights, out_biases = sess.run( [logits, lr.weights, lr.biases], feed_dict=feed_dict) print("accuracy: {}, f1: {}, auc: {}".format( metrics.calc_accuracy(out_logits, in_labels), metrics.calc_f1(out_logits, in_labels, log_confusion_matrix=True), metrics.calc_auc(out_logits, in_labels))) print("weights: ", out_weights) print("biases: ", out_biases)
def obj(args): P0 = P.copy() P0.update(args) perf_mat = np.empty(shape=(2,P.get('runs'))) for run in range(P0.get('runs')): G, D, _, _ = GAN.train_GD(P0, DL_L, DL_V, name=P0.get('name')+'_%d'%run) G.eval();D.eval(); with torch.no_grad(): YV = floatTensor(pp.get_one_hot_labels(P0,num=P0.get('batch_size'))) perf_mat[0,run] = calc_accuracy(D(torch.cat((G(torch.cat((floatTensor(np.random.normal(0,1,(P0.get('batch_size'),P0.get('noise_shape')))),YV),dim=1)),YV),dim=1)),floatTensor(P0.get('batch_size'),1).fill_(0.0)) perf_mat[1,run] = np.mean([calc_accuracy(D(torch.cat((XV,YV),dim=1)),floatTensor(XV.shape[0],1).fill_(1.0)) for XV, YV in DL_V]) val = np.mean((0.5-perf_mat[0])**2) + 0.1 * np.mean((1-perf_mat[1])**2) P0.log(f"loss = {val:.5f} Accuracy D = {np.mean(perf_mat):.5f} | vs G = {np.mean(perf_mat[0]):.5f} | vs real = {np.mean(perf_mat[1]):.5f}",name='hyperopt') return val
def obj(args): P0 = P.copy() P0.update(args) P0.log("Check Params: "+", ".join([str(key)+' = '+ ("'"+val+"'" if isinstance(val,str) else str(val)) for key,val in args.items()]),name='hyperopt') perf_mat = np.empty(shape=(2,P.get('runs'),len(DL_V))) for run in range(P0.get('runs')): C, _, _ = GAN.train_Base(P0, DL_L, DL_V, name=P0.get('name')+'_%d'%run) C.eval() with torch.no_grad(): for i,(XV, YV) in enumerate(DL_V): perf_mat[0,run,i] = calc_f1score(C(XV), YV, average = 'weighted') perf_mat[1,run,i] = calc_accuracy(C(XV), YV) perf = np.mean(perf_mat.reshape(2,-1),axis=1) P0.log(f"F1: {perf[0]:.5f} | Accuracy: {perf[1]:.5f}",name='hyperopt') return -perf[0]
def train_GD(P, DL_L, DL_V, mat_accuracy=None, mat_f1_score=None, name=None): name = name if name is not None else P.get('name') D_Loss = torch.nn.BCELoss() if P.get('CUDA') and torch.cuda.is_available(): D_Loss.cuda() floatTensor = torch.cuda.FloatTensor else: floatTensor = torch.FloatTensor if mat_accuracy is None: mat_accuracy = np.zeros( (2, int(P.get('epochs_GD') / P.get('save_step')) + 1)) if mat_f1_score is None: mat_f1_score = np.zeros( (2, int(P.get('epochs_GD') / P.get('save_step')) + 1)) G = network.load_G(P) D = network.load_D(P) optimizer_G = network.get_optimiser(P, 'G', G.parameters()) optimizer_D = network.get_optimiser(P, 'D', D.parameters()) for epoch in range(P.get('epochs_GD')): if P.get('print_epoch'): loss_G = [] loss_D = [] G.train() D.train() for i, (X1, Y1) in enumerate(DL_L, 1): # ------------------- # Train the discriminator to label real samples # ------------------- W1 = torch.cat((X1, Y1), dim=1) R1 = floatTensor(W1.shape[0], 1).fill_(1.0) optimizer_D.zero_grad() A1 = D(W1) loss = D_Loss(A1, R1) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Create Synthetic Data # ------------------- optimizer_G.zero_grad() if P.get('G_label_sample'): # Selected Labels from a uniform distribution of available labels Y3 = floatTensor( pp.get_one_hot_labels(P, num=Y1.shape[0] * P.get('G_label_factor'))) else: # Select labels from current training batch Y3 = torch.cat(([Y1 for _ in range(P.get('G_label_factor'))]), dim=0) Z = floatTensor( np.random.normal(0, 1, (Y3.shape[0], P.get('noise_shape')))) I3 = torch.cat((Z, Y3), dim=1) X3 = G(I3) W3 = torch.cat((X3, Y3), dim=1) # ------------------- # Train the generator to fool the discriminator # ------------------- A3 = D(W3) R3 = floatTensor(W3.shape[0], 1).fill_(1.0) loss = D_Loss(A3, R3) loss.backward() optimizer_G.step() if P.get('print_epoch'): loss_G.append(loss) # ------------------- # Train the discriminator to label synthetic samples # ------------------- optimizer_D.zero_grad() A3 = D(W3.detach()) F3 = floatTensor(W3.shape[0], 1).fill_(0.0) loss = D_Loss(A3, F3) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Post Epoch # ------------------- if P.get('print_epoch'): logString = f"[Epoch {epoch+1}/{P.get('epochs')}] [G loss: {np.mean([loss.item() for loss in loss_G])}] [D loss: {np.mean([loss.item() for loss in loss_D])}]" P.log(logString, save=False) if (epoch + 1) % P.get('save_step') == 0: idx = int(epoch / P.get('save_step')) + 1 D_acc = np.zeros((2, len(DL_V))) D_f1 = np.zeros((2, len(DL_V))) G_f1 = np.zeros((len(DL_V))) G.eval() D.eval() with torch.no_grad(): for i, (XV, YV) in enumerate(DL_V): # Generate Synthetic Data Z = floatTensor( np.random.normal(0, 1, (YV.shape[0], P.get('noise_shape')))) IV = torch.cat((Z, YV), dim=1) XG = G(IV) # Estimate Discriminator Accuracy WV1 = torch.cat((XV, YV), dim=1) WV3 = torch.cat((XG, YV), dim=1) RV1 = floatTensor(WV1.shape[0], 1).fill_(1.0) FV3 = floatTensor(WV3.shape[0], 1).fill_(0.0) RV3 = floatTensor(WV3.shape[0], 1).fill_(1.0) AV1 = D(WV1) AV3 = D(WV3) D_acc[0, i] = calc_accuracy(AV1, RV1) D_acc[1, i] = calc_accuracy(AV3, FV3) D_f1[0, i] = calc_f1score(AV1, RV1) D_f1[1, i] = calc_f1score(AV3, FV3) G_f1[i] = calc_f1score(AV3, RV3) D_acc = np.mean(D_acc, axis=1) acc_D = np.mean(D_acc) mat_accuracy[1, idx] = acc_D acc_G = 1.0 - D_acc[1] mat_accuracy[0, idx] = acc_G mat_f1_score[0, idx] = np.mean(G_f1) mat_f1_score[1, idx] = np.mean(D_f1) logString = f"[{name}] [Epoch {epoch+1}/{P.get('epochs')}] [G F1: {mat_f1_score[0,idx]} acc: {acc_G}] [D F1: {mat_f1_score[1,idx]} acc: {acc_D} | vs Real: {D_acc[0]} | vs G: {D_acc[1]}]" P.log(logString, save=True) return G, D, mat_accuracy, mat_f1_score
def train_GAN(P, DL_L, DL_U_iter, DL_V, name=None): name = name if name is not None else P.get('name') # ------------------- # Parameters # ------------------- #P.log(str(P)) plt.close('all') # ------------------- # CUDA # ------------------- D_Loss = torch.nn.BCELoss() C_Loss = network.CrossEntropyLoss_OneHot() if P.get('CUDA') and torch.cuda.is_available(): D_Loss.cuda() C_Loss.cuda() floatTensor = torch.cuda.FloatTensor #P.log("CUDA Training.") #network.clear_cache() else: floatTensor = torch.FloatTensor #P.log("CPU Training.") # ------------------- # Metrics # ------------------- mat_accuracy = np.zeros((3, int( (P.get('epochs')) / P.get('save_step')) + 1)) mat_f1_score = np.zeros((3, int( (P.get('epochs')) / P.get('save_step')) + 1)) # ------------------- # Networks # ------------------- G, D, mat_accuracy, mat_f1_score = train_GD(P, DL_L, DL_V, mat_accuracy, mat_f1_score, name) C = network.load_C(P) # ------------------- # Optimizers # ------------------- optimizer_G = network.get_optimiser(P, 'G', G.parameters()) optimizer_D = network.get_optimiser(P, 'D', D.parameters()) optimizer_C = network.get_optimiser(P, 'C', C.parameters()) # ------------------- # Training # ------------------- for epoch in range(P.get('epochs_GD'), P.get('epochs')): if P.get('print_epoch'): running_loss_G = 0.0 running_loss_D = 0.0 running_loss_C = 0.0 G.train() D.train() C.train() """ X1, P1 - Labelled Data, predicted Labels (C) | Regular training of classifier W1 = (X1, Y1), A1 - Labelled Data, actual Labels, predicted Authenticity (D) | Real samples W2 = (X2, Y2), A2 - Unlabelled Data, predicted Labels (C), predicted Authenticity (D) | Real data with fake labels W3 = (X3, Y3), A3 - Synthetic Data (G), actual Labels, predicted Authenticity (D) | Fake data with real labels W4 = (X4, Y4), A4 - Unlabbeled Data, predicted Labels (C), predicted Authenticity (D) | Fake positive to prevent overfitting XV, YV, PV - Validation Data, actual Labels, predicted Labels (C) | Validation samples R1, F2, F3, R4 - Real/Fake Labels """ for i, (X1, Y1) in enumerate(DL_L, 1): if P.get('print_epoch'): loss_G = [] loss_D = [] loss_C = [] # ------------------- # Train the classifier on real samples # ------------------- W1 = torch.cat((X1, Y1), dim=1) R1 = floatTensor(W1.shape[0], 1).fill_(1.0) if P.get('C_basic_train'): optimizer_C.zero_grad() P1 = C(X1) loss = C_Loss(P1, Y1) loss.backward() optimizer_C.step() if P.get('print_epoch'): loss_C.append(loss) # ------------------- # Train the discriminator to label real samples # ------------------- optimizer_D.zero_grad() A1 = D(W1) loss = D_Loss(A1, R1) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Classify unlabelled data # ------------------- optimizer_C.zero_grad() X2 = DL_U_iter.get_next()[0] Y2 = C(X2) W2 = torch.cat((X2, Y2), dim=1) # ------------------- # Train the classifier to label unlabelled samples # ------------------- A2 = D(W2) R2 = floatTensor(W2.shape[0], 1).fill_(1.0) loss = D_Loss(A2, R2) loss.backward() optimizer_C.step() if P.get('print_epoch'): loss_C.append(loss) # ------------------- # Train the discriminator to label predicted samples # ------------------- optimizer_D.zero_grad() A2 = D(W2.detach()) F2 = floatTensor(W2.shape[0], 1).fill_(0.0) loss = D_Loss(A2, F2) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Train the discriminator to label fake positive samples # ------------------- if P.get('D_fake_step') is not None and ( epoch + 1) % P.get('D_fake_step') == 0: X4 = DL_U_iter.get_next()[0] Y4 = C(X4) W4 = torch.cat((X4, Y4), dim=1) optimizer_D.zero_grad() A4 = D(W4.detach()) R4 = floatTensor(W4.shape[0], 1).fill_(1.0) loss = D_Loss(A4, R4) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Create Synthetic Data # ------------------- optimizer_G.zero_grad() if P.get('G_label_sample'): # Selected Labels from a uniform distribution of available labels Y3 = floatTensor( pp.get_one_hot_labels(P, num=Y1.shape[0] * P.get('G_label_factor'))) else: # Select labels from current training batch Y3 = torch.cat(([Y1 for _ in range(P.get('G_label_factor'))]), dim=0) Z = floatTensor( np.random.normal(0, 1, (Y3.shape[0], P.get('noise_shape')))) I3 = torch.cat((Z, Y3), dim=1) X3 = G(I3) W3 = torch.cat((X3, Y3), dim=1) # ------------------- # Train the generator to fool the discriminator # ------------------- A3 = D(W3) R3 = floatTensor(W3.shape[0], 1).fill_(1.0) loss = D_Loss(A3, R3) loss.backward() optimizer_G.step() if P.get('print_epoch'): loss_G.append(loss) # ------------------- # Train the discriminator to label synthetic samples # ------------------- optimizer_D.zero_grad() A3 = D(W3.detach()) F3 = floatTensor(W3.shape[0], 1).fill_(0.0) loss = D_Loss(A3, F3) loss.backward() optimizer_D.step() if P.get('print_epoch'): loss_D.append(loss) # ------------------- # Calculate overall loss # ------------------- if P.get('print_epoch'): running_loss_G += np.mean([loss.item() for loss in loss_G]) running_loss_D += np.mean([loss.item() for loss in loss_D]) running_loss_C += np.mean([loss.item() for loss in loss_C]) # ------------------- # Post Epoch # ------------------- if P.get('print_epoch'): logString = f"[Epoch {epoch+1}/{P.get('epochs')}] [G loss: {running_loss_G/(i)}] [D loss: {running_loss_D/(i)}] [C loss: {running_loss_C/(i)}]" P.log(logString, save=False) if (epoch + 1) % P.get('save_step') == 0: idx = int(epoch / P.get('save_step')) + 1 D_acc = np.zeros((3, len(DL_V))) C_acc = np.zeros(len(DL_V)) D_f1 = np.zeros((3, len(DL_V))) C_f1 = np.zeros((len(DL_V))) G_f1 = np.zeros((len(DL_V))) G.eval() D.eval() C.eval() with torch.no_grad(): for i, data in enumerate(DL_V): XV, YV = data # Predict labels PV = C(XV) # Generate Synthetic Data Z = floatTensor( np.random.normal(0, 1, (YV.shape[0], P.get('noise_shape')))) IV = torch.cat((Z, YV), dim=1) XG = G(IV) # Estimate Discriminator Accuracy WV1 = torch.cat((XV, YV), dim=1) WV2 = torch.cat((XV, PV), dim=1) WV3 = torch.cat((XG, YV), dim=1) RV1 = floatTensor(WV1.shape[0], 1).fill_(1.0) FV2 = floatTensor(WV2.shape[0], 1).fill_(0.0) FV3 = floatTensor(WV3.shape[0], 1).fill_(0.0) RV3 = floatTensor(WV3.shape[0], 1).fill_(1.0) AV1 = D(WV1) AV2 = D(WV2) AV3 = D(WV3) D_acc[0, i] = calc_accuracy(AV1, RV1) D_acc[1, i] = calc_accuracy(AV2, FV2) D_acc[2, i] = calc_accuracy(AV3, FV3) C_acc[i] = calc_accuracy(PV, YV) D_f1[0, i] = calc_f1score(AV1, RV1) D_f1[1, i] = calc_f1score(AV2, FV2) D_f1[2, i] = calc_f1score(AV3, FV3) C_f1[i] = calc_f1score(PV, YV, average='macro') G_f1[i] = calc_f1score(AV3, RV3) D_acc = np.mean(D_acc, axis=1) acc_D = .5 * D_acc[0] + .25 * D_acc[1] + .25 * D_acc[2] mat_accuracy[1, idx] = acc_D acc_C_real = np.mean(C_acc) acc_C_vs_D = 1.0 - D_acc[1] acc_C = .5 * acc_C_real + .5 * acc_C_vs_D mat_accuracy[2, idx] = acc_C_real acc_G = 1.0 - D_acc[2] mat_accuracy[0, idx] = acc_G mat_f1_score[0, idx] = np.mean(G_f1) mat_f1_score[1, idx] = np.mean(D_f1) mat_f1_score[2, idx] = np.mean(C_f1) logString = f"[{name}] [Epoch {epoch+1}/{P.get('epochs')}] [G F1: {mat_f1_score[0,idx]} acc: {acc_G}] [D F1: {mat_f1_score[1,idx]} acc: {acc_D} | vs Real: {D_acc[0]} | vs G: {D_acc[2]} | vs C: {D_acc[1]}] [C F1: {mat_f1_score[2,idx]} acc: {acc_C} | vs Real: {acc_C_real} | vs D: {acc_C_vs_D}]" P.log(logString, save=True) # ------------------- # Post Training # ------------------- if P.get('save_GAN'): network.save_GAN(name, G, D, C) return G, D, C, mat_accuracy, mat_f1_score
def main(dataset): """ Tainer """ # build graph tf.reset_default_graph() lr = logistic_regressor.LogisticRegressor(feature_num=conf.FEATURE_NUM, learning_rate=conf.LEARNING_RATE, random_seed=None) saver, logits, loss, train_op, stat_merged = lr.build_graph() # training with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) # log dir log_dir = conf.LOG_DIR if os.path.exists(log_dir): shutil.rmtree(log_dir) summary_writer = tf.summary.FileWriter(log_dir, graph=tf.get_default_graph()) # checkpoint dir chkpt_dir = conf.CHKPT_DIR if os.path.exists(chkpt_dir): shutil.rmtree(chkpt_dir) if not os.path.isdir(chkpt_dir): os.makedirs(chkpt_dir) for epoch in range(conf.EPOCHES): batch_cnt = 0 batches_per_epoch = math.floor( (len(dataset[0]) - 1) * 1.0 / conf.BATCH_SIZE) + 1 best_loss = np.inf cur_loss = np.inf cur_accuracy = 0 training_data = list(zip(dataset[0], dataset[1])) random.shuffle(training_data) for tu in utils.batch(training_data, n=conf.BATCH_SIZE): X, y = zip(*tu) y = np.expand_dims(y, 1) feed_dict = {lr.input_feature_vectors: X, lr.input_labels: y} sess.run(train_op, feed_dict=feed_dict) batch_cnt += 1 global_step = epoch * batches_per_epoch + batch_cnt if global_step % conf.DISPLAY_STEP == 0: in_f = dataset[0] in_l = np.expand_dims(dataset[1], 1) feed_dict = { lr.input_feature_vectors: in_f, lr.input_labels: in_l } cur_loss, cur_logits = sess.run([loss, logits], feed_dict=feed_dict) summary_train = sess.run(stat_merged, feed_dict=feed_dict) summary_writer.add_summary(summary_train, global_step=global_step) print("epoch: {}, global_step: {}, loss: {}, " "accuracy: {}, f1: {}, auc: {}".format( epoch, global_step, cur_loss, metrics.calc_accuracy(cur_logits, in_l), metrics.calc_f1(cur_logits, in_l), metrics.calc_auc(cur_logits, in_l))) if cur_loss < best_loss: best_loss = cur_loss saver.save(sess, '{}/model'.format(chkpt_dir))