def test_samples(): samplefiles = [ '{}normal/Multi_4_W1_1', '{}illum1/Multi_4_W1_1', '{}illum2/Multi_4_W1_1', '{}normal/Multi_1_W1_1', '{}normal/Multi_4_W1_5' ] samplefiles = list( map( lambda x: x.format( '/home/louishsu/Work/Workspace/ECUST2019_64x64/DATA1/1/Multi/' ), samplefiles)) ## 23 channels modelpath = "/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/recognize_vgg11_bn_split_64x64_1_63subjects_models/recognize_vgg11_bn_split_64x64_1_23chs_550sta_20nm.pkl" model = torch.load( modelpath, map_location='cuda' if torch.cuda.is_available() else 'cpu') images = [] for samplefile in samplefiles: images += [ RecognizeDataset._load_image(samplefile, 'Multi', [550 + i * 20 for i in range(23)]).unsqueeze(0) ] images = torch.cat(images, 0) y_pred_23chs = model(images).detach().numpy() ## single channel MODELPATH = "/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/recognize_vgg11_bn_split_64x64_1_63subjects_models/recognize_vgg11_bn_split_64x64_1_1chs_{}sta_20nm.pkl" for samplefile in samplefiles: y_pred = [] for ch in [550 + i * 20 for i in range(23)]: image = RecognizeDataset._load_image(samplefile, 'Multi', [ch]).unsqueeze(0) model = torch.load( MODELPATH.format(ch), map_location='cuda' if torch.cuda.is_available() else 'cpu') y_pred += [model(image).detach().numpy()] y_pred += [ y_pred_23chs[samplefiles.index(samplefile)].reshape((1, -1)) ] y_pred = np.concatenate(y_pred, axis=0) filename = '/home/louishsu/Desktop/' + '_'.join( samplefile.split('/')[-2:]) np.save(filename + '.npy', y_pred)
def __init__(self, datapath, filelist, usedChannels): filelist = list( map( lambda x: os.path.join('/'.join(datapath.split('/')[:-1]), x.strip()), filelist)) self.samplelist = list( map( lambda x: [ RecognizeDataset._load_image(x, 'Multi', usedChannels), getLabel(x) - 1 ], filelist))
def test(configer): ## datasets testset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'test', configer.usedChannels) testloader = DataLoader(testset, configer.batchsize_test, shuffle=False) ## model modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl' assert os.path.exists(modelpath), 'please train first! ' model = torch.load(modelpath) if configer.cuda and is_available(): model.cuda() ## loss loss = nn.CrossEntropyLoss() ## log logpath = os.path.join(configer.logspath, configer.modelname) ftest = open(os.path.join(logpath, 'test_log.txt'), 'w') ## initialize acc_test = [] loss_test = [] output = None ArcMargin = ArcMarginProduct(128, configer.n_class) ## start testing model.eval() for i_batch, (X, y) in enumerate(testloader): # get batch X = Variable(X.float()) y = Variable(y) if configer.cuda and is_available(): X = X.cuda() y = y.cuda() # forward if configer.modelbase == 'recognize_mobilefacenet': raw_logits = model(X) y_pred_prob = ArcMargin(raw_logits, y) else: y_pred_prob = model(X) #y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # log print_log = "{} || Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\ format(getTime(), i_batch, len(testset) // configer.batchsize, acc_i, loss_i) print(print_log) ftest.write(print_log + '\n') loss_test += [loss_i.detach().cpu().numpy()] acc_test += [acc_i.cpu().numpy()] # save output if output is None: output = y_pred_prob.detach().cpu().numpy() else: output = np.concatenate( [output, y_pred_prob.detach().cpu().numpy()], axis=0) print( '------------------------------------------------------------------------------------------------------------------' ) loss_test = np.mean(np.array(loss_test)) acc_test = np.mean(np.array(acc_test)) print_log = "{} || test | acc: {:2.2%}, loss: {:4.4f}".\ format(getTime(), acc_test, loss_test) print(print_log) ftest.write(print_log + '\n') np.save(os.path.join(logpath, 'test_out.npy'), output) print( '==================================================================================================================' ) ftest.close()
def main_pca(): from tensorPCA import NDarrayPCA for splitidx in range(1, 6): configer = EasyDict() configer.dsize = (64, 64) configer.datatype = 'Multi' configer.n_epoch = 500 configer.lrbase = 0.0001 configer.n_channel = 23 configer.n_class = 63 configer.batchsize = 32 configer.stepsize = 250 configer.gamma = 0.2 configer.cuda = True configer.splitmode = 'split_{}x{}_{}'.format(configer.dsize[0], configer.dsize[1], splitidx) configer.modelbase = 'recognize_vgg11_bn' configer.usedChannels = [550+i*20 for i in range(23)] configer.n_usedChannels = len(configer.usedChannels) configer.modelname = '{}_{}_{}_PCA'.\ format(configer.modelbase, configer.splitmode, '_'.join(list(map(str, configer.usedChannels)))) configer.datapath = '/home/louishsu/Work/Workspace/ECUST2019_{}x{}'.\ format(configer.dsize[0], configer.dsize[1]) configer.logspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/logs/{}_{}_{}subjects_logs'.\ format(configer.modelbase, configer.splitmode, configer.n_class) configer.mdlspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/{}_{}_{}subjects_models'.\ format(configer.modelbase, configer.splitmode, configer.n_class) trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels) validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels) trainloader = DataLoader(trainset, configer.batchsize, shuffle=True) validloader = DataLoader(validset, configer.batchsize, shuffle=False) for chs in range(10, 24): print(getTime(), splitidx, 'reduce to ', chs, '...') ## fit pca decomposer = NDarrayPCA(n_components=[chs, 64, 64]) traindata = np.concatenate([trainset.samplelist[i][0].numpy()[np.newaxis] for i in range(len(trainset.samplelist))], axis=0) decomposer.fit(traindata) del traindata ## model modelpath = os.path.join(configer.mdlspath, configer.modelname) + '{}chs.pkl'.format(chs) modeldir = '/'.join(modelpath.split('/')[:-1]) if not os.path.exists(modeldir): os.makedirs(modeldir) model = modeldict[configer.modelbase](chs, configer.n_class, configer.dsize[0]) if configer.cuda and is_available(): model.cuda() ## loss loss = nn.CrossEntropyLoss() params = model.parameters() optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3) scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma) logpath = os.path.join(configer.logspath, configer.modelname) + '{}chs'.format(chs) if not os.path.exists(logpath): os.makedirs(logpath) logger = SummaryWriter(logpath) ## initialize acc_train = 0. acc_valid = 0. loss_train = float('inf') loss_valid = float('inf') loss_valid_last = float('inf') ## start training for i_epoch in range(configer.n_epoch): if configer.cuda and is_available(): empty_cache() scheduler.step(i_epoch) acc_train = []; acc_valid = [] loss_train = []; loss_valid = [] model.train() for i_batch, (X, y) in enumerate(trainloader): X = torch.from_numpy(decomposer.transform(X.numpy())) # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # backward optimizer.zero_grad() loss_i.backward() optimizer.step() loss_train += [loss_i.detach().cpu().numpy()] acc_train += [acc_i.cpu().numpy()] model.eval() for i_batch, (X, y) in enumerate(validloader): X = torch.from_numpy(decomposer.transform(X.numpy())) # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) loss_valid += [loss_i.detach().cpu().numpy()] acc_valid += [acc_i.cpu().numpy()] loss_train = np.mean(np.array(loss_train)) acc_train = np.mean(np.array(acc_train)) loss_valid = np.mean(np.array(loss_valid)) acc_valid = np.mean(np.array(acc_valid)) logger.add_scalars('accuracy', {'train': acc_train, 'valid': acc_valid}, i_epoch) logger.add_scalars('logloss', {'train': loss_train, 'valid': loss_valid}, i_epoch) logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch) if loss_valid_last > loss_valid: loss_valid_last = loss_valid torch.save(model, modelpath) ## start testing model.eval() testset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'test', configer.usedChannels) testloader = DataLoader(testset, configer.batchsize, shuffle=False) loss_test = [] acc_test = [] output = None for i_batch, (X, y) in enumerate(testloader): X = torch.from_numpy(decomposer.transform(X.numpy())) # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # log loss_test += [loss_i.detach().cpu().numpy()] acc_test += [acc_i.cpu().numpy()] # save output if output is None: output = y_pred_prob.detach().cpu().numpy() else: output = np.concatenate([output, y_pred_prob.detach().cpu().numpy()], axis=0) # print('------------------------------------------------------------------------------------------------------------------') loss_test = np.mean(np.array(loss_test)) acc_test = np.mean(np.array(acc_test)) print_log = "{} || test | acc: {:2.2%}, loss: {:4.4f}".\ format(getTime(), acc_test, loss_test) print(print_log) with open(os.path.join(logpath, 'test_log.txt'), 'w') as f: f.write(print_log + '\n') np.save(os.path.join(logpath, 'test_out.npy'), output)
def main_finetune_channels(): # 波段选择依据 # 最优的波段排序: # [850, 870, 930, 730, 790, 910, 770, 750, 670, 950, 990, 830, 890, 810, 970, 690, 710, 650, 590, 570, 630, 610, 550] # 依次增加一个波段, 前一个模型进行微调 CHANNEL_SORT = [850, 870, 930, 730, 790, 910, 770, 750, 670, 950, 990, 830, 890, 810, 970, 690, 710, 650, 590, 570, 630, 610, 550] for splitidx in range(4, 5): usedChannelsList = [CHANNEL_SORT[:i+1] for i in range(23)] # for i_usedChannels in range(len(usedChannelsList)): for i_usedChannels in [4, 6]: usedChannels = usedChannelsList[i_usedChannels] print(getTime(), splitidx, len(usedChannels), '...') configer = EasyDict() configer.dsize = (64, 64) configer.datatype = 'Multi' configer.n_epoch = 300 configer.lrbase = 0.001 configer.n_channel = 23 configer.n_class = 63 configer.batchsize = 32 configer.stepsize = 250 configer.gamma = 0.2 configer.cuda = True configer.splitmode = 'split_{}x{}_{}'.format(configer.dsize[0], configer.dsize[1], splitidx) configer.modelbase = 'recognize_mobilenet' configer.usedChannels = usedChannels configer.n_usedChannels = len(configer.usedChannels) configer.modelname = '{}_{}_{}_finetune'.\ format(configer.modelbase, configer.splitmode, '_'.join(list(map(str, configer.usedChannels)))) configer.datapath = '/home/louishsu/Work/Workspace/ECUST2019_{}x{}'.\ format(configer.dsize[0], configer.dsize[1]) configer.logspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/logs/{}_{}_{}subjects_logs'.\ format(configer.modelbase, configer.splitmode, configer.n_class) configer.mdlspath = '/home/louishsu/Work/Workspace/HUAWEI/pytorch/modelfiles/{}_{}_{}subjects_models'.\ format(configer.modelbase, configer.splitmode, configer.n_class) ## datasets trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels) validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels) trainloader = DataLoader(trainset, configer.batchsize, shuffle=True) validloader = DataLoader(validset, configer.batchsize, shuffle=False) ## ============================================================================================ ## model modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl' modeldir = '/'.join(modelpath.split('/')[:-1]) if not os.path.exists(modeldir): os.makedirs(modeldir) if i_usedChannels == 0: model = modeldict[configer.modelbase](configer.n_usedChannels, configer.n_class, configer.dsize[0]) params = model.parameters() torch.save(model, modelpath) else: modelpath_pretrain = os.path.join( modeldir, '{}_{}_{}_finetune.pkl'.format(configer.modelbase, configer.splitmode, '_'.join(list(map(str, usedChannelsList[i_usedChannels-1]))))) model = torch.load(modelpath_pretrain) model.features[0] = nn.Conv2d(len(usedChannels), 64, 3, stride=1, padding=1) params = [ {'params': model.features[1:].parameters(), 'lr': configer.lrbase*0.01, }, {'params': model.features[0].parameters(),} ] torch.save(model, modelpath) if configer.cuda and is_available(): model.cuda() ## ============================================================================================ ## optimizer optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3) ## loss loss = nn.CrossEntropyLoss() ## learning rate scheduler scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma) ## log logpath = os.path.join(configer.logspath, configer.modelname) if not os.path.exists(logpath): os.makedirs(logpath) logger = SummaryWriter(logpath) ## initialize acc_train = 0. acc_valid = 0. loss_train = float('inf') loss_valid = float('inf') loss_valid_last = float('inf') ## start training for i_epoch in range(configer.n_epoch): if configer.cuda and is_available(): empty_cache() scheduler.step(i_epoch) acc_train = []; acc_valid = [] loss_train = []; loss_valid = [] model.train() for i_batch, (X, y) in enumerate(trainloader): # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # backward optimizer.zero_grad() loss_i.backward() optimizer.step() loss_train += [loss_i.detach().cpu().numpy()] acc_train += [acc_i.cpu().numpy()] model.eval() for i_batch, (X, y) in enumerate(validloader): # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) loss_valid += [loss_i.detach().cpu().numpy()] acc_valid += [acc_i.cpu().numpy()] loss_train = np.mean(np.array(loss_train)) acc_train = np.mean(np.array(acc_train)) loss_valid = np.mean(np.array(loss_valid)) acc_valid = np.mean(np.array(acc_valid)) logger.add_scalars('accuracy', {'train': acc_train, 'valid': acc_valid}, i_epoch) logger.add_scalars('logloss', {'train': loss_train, 'valid': loss_valid}, i_epoch) logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch) if loss_valid_last > loss_valid: loss_valid_last = loss_valid torch.save(model, modelpath) test(configer)
def train(configer): """ Update: 2019.04.24: 固定权值 """ ## datasets trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels) validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels) trainloader = DataLoader(trainset, configer.batchsize, shuffle=True) validloader = DataLoader(validset, configer.batchsize, shuffle=False) ## model: pre-initialized modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl' modeldir = '/'.join(modelpath.split('/')[:-1]) if not os.path.exists(modeldir): os.makedirs(modeldir) preInitdir = os.path.join('/'.join(configer.mdlspath.split('/')[:-1]), "preinit") if not os.path.exists(preInitdir): os.makedirs(preInitdir) preInitmodelpath = os.path.join(preInitdir, configer.modelbase + '.pkl') model = modeldict[configer.modelbase](configer.n_usedChannels, configer.n_class, configer.dsize[0]) if not os.path.exists(preInitmodelpath): model_state = model.state_dict() torch.save(model_state, preInitmodelpath) else: preinit_state = torch.load(preInitmodelpath) model_state = model.state_dict() toload_state = {k: v for k, v in preinit_state.items() \ if preinit_state[k].shape==model_state[k].shape} model_state.update(toload_state) model.load_state_dict(model_state) if configer.cuda and is_available(): model.cuda() ## loss loss = nn.CrossEntropyLoss() ## optimizer params = model.parameters() optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3) ## learning rate scheduler scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma) ## log logpath = os.path.join(configer.logspath, configer.modelname) if not os.path.exists(logpath): os.makedirs(logpath) logger = SummaryWriter(logpath) ## initialize elapsed_time = 0 total_time = 0 start_time = 0 acc_train = 0. acc_valid = 0. loss_train = float('inf') loss_valid = float('inf') loss_valid_last = float('inf') ## start training for i_epoch in range(configer.n_epoch): if configer.cuda and is_available(): empty_cache() scheduler.step(i_epoch) acc_train = [] acc_valid = [] loss_train = [] loss_valid = [] model.train() start_time = time.time() for i_batch, (X, y) in enumerate(trainloader): # get batch X = Variable(X.float()) y = Variable(y) if configer.cuda and is_available(): X = X.cuda() y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # backward optimizer.zero_grad() loss_i.backward() optimizer.step() # time duration_time = time.time() - start_time start_time = time.time() elapsed_time += duration_time total_time = duration_time * configer.n_epoch * len( trainset) // configer.batchsize # log # print_log = "{} || Elapsed: {:.4f}h | Left: {:.4f}h | FPS: {:4.2f} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || lr: {:.6f} | accuracy: {:2.2%}, loss: {:4.4f}".\ # format(getTime(), elapsed_time/3600, (total_time - elapsed_time)/3600, configer.batchsize / duration_time, # i_epoch, configer.n_epoch, i_batch, len(trainset) // configer.batchsize, # scheduler.get_lr()[-1], acc_i, loss_i) # print(print_log) loss_train += [loss_i.detach().cpu().numpy()] acc_train += [acc_i.cpu().numpy()] # print('------------------------------------------------------------------------------------------------------------------') model.eval() for i_batch, (X, y) in enumerate(validloader): # get batch X = Variable(X.float()) y = Variable(y) if configer.cuda and is_available(): X = X.cuda() y = y.cuda() # forward y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # log # print_log = "{} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\ # format(getTime(), i_epoch, configer.n_epoch, i_batch, len(validset) // configer.batchsize, acc_i, loss_i) # print(print_log) loss_valid += [loss_i.detach().cpu().numpy()] acc_valid += [acc_i.cpu().numpy()] # print('------------------------------------------------------------------------------------------------------------------') loss_train = np.mean(np.array(loss_train)) acc_train = np.mean(np.array(acc_train)) loss_valid = np.mean(np.array(loss_valid)) acc_valid = np.mean(np.array(acc_valid)) # print_log = "{} || Epoch: [{:3d}]/[{:3d}] || lr: {:.6f} || train | acc: {:2.2%}, loss: {:4.4f} || valid | acc: {:2.2%}, loss: {:4.4f}".\ # format(getTime(), i_epoch, configer.n_epoch, scheduler.get_lr()[-1], acc_train, loss_train, acc_valid, loss_valid) # print(print_log) logger.add_scalars('accuracy', { 'train': acc_train, 'valid': acc_valid }, i_epoch) logger.add_scalars('logloss', { 'train': loss_train, 'valid': loss_valid }, i_epoch) logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch) # print('------------------------------------------------------------------------------------------------------------------') if loss_valid_last > loss_valid: loss_valid_last = loss_valid torch.save(model, modelpath)
def main_3_5(make_table_figure=False): datatypes = ["Multi", "RGB"] splitcounts = [i for i in range(1, 11)] H = len(splitcounts) loss = nn.CrossEntropyLoss() if make_table_figure: illum_types = ["illum1", "illum2", "illum3", "normal"] positions = [i + 1 for i in range(7)] # 共7个拍摄角度,编号 1 ~ 7 glass_types = [1, 5, 6] # `1`表示无眼镜,`5`表示戴眼镜,`6`表示太阳镜 for datatype in datatypes: print("Generating tables and figures [{}]...".format(datatype)) usedChannels = [i for i in range(1, 26)] \ if datatype == "Multi" else "RGB" data_acc_illum_types = np.zeros(shape=(H, len(illum_types))) data_loss_illum_types = np.zeros(shape=(H, len(illum_types))) data_acc_positions = np.zeros(shape=(H, len(positions ))) data_loss_positions = np.zeros(shape=(H, len(positions ))) data_acc_glass_types = np.zeros(shape=(H, len(glass_types))) data_loss_glass_types = np.zeros(shape=(H, len(glass_types))) for i in range(len(splitcounts)): splitcount = splitcounts[i] ## 获取configer configer = get_configer(datatype=datatype, splitcount=splitcount, usedChannels=usedChannels) ## 读取保存的测试结果 logpath = os.path.join(configer.logspath, configer.modelname) print(logpath) y_pred_prob = np.load(os.path.join(logpath, 'test_out.npy')) ## 读取文件列表 testset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'test', configer.usedChannels) y_true = np.array(list(map(lambda x: x[1], testset.samplelist))) test_list = testset.filelist test_attr_list = list(map(lambda x: ImageAttributes(x), test_list)) del testset ## 分析光照 for j in range(len(illum_types)): illum_type = illum_types[j] # FIXME: # index = list(map(lambda x: x.illum_type==illum_type, test_attr_list)) index = list(map(lambda x: x.illum_type==illum_type and \ # x.glass_type==1 and \ x.position==4, test_attr_list)) index = np.array(index, dtype=np.bool) y_pred_prob_sub = torch.tensor(y_pred_prob[index]) y_true_sub = torch.tensor(y_true[index]) data_acc_illum_types [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy() data_loss_illum_types[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy() ## 分析位置 for j in range(len(positions)): position = positions[j] # FIXME: # index = list(map(lambda x: x.position==position, test_attr_list)) index = list(map(lambda x: x.position==position and \ x.glass_type==1, test_attr_list)) index = np.array(index, dtype=np.bool) y_pred_prob_sub = torch.tensor(y_pred_prob[index]) y_true_sub = torch.tensor(y_true[index]) data_acc_positions [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy() data_loss_positions[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy() ## 分析眼镜 for j in range(len(glass_types)): glass_type = glass_types[j] index = list(map(lambda x: x.glass_type==glass_type, test_attr_list)) index = np.array(index, dtype=np.bool) y_pred_prob_sub = torch.tensor(y_pred_prob[index]) y_true_sub = torch.tensor(y_true[index]) data_acc_glass_types [i, j] = accuracy(y_pred_prob_sub, y_true_sub).cpu().numpy() data_loss_glass_types[i, j] = loss(y_pred_prob_sub, y_true_sub).cpu().numpy() ## 绘制表格 rows_name = [str(i) for i in splitcounts] + ['average'] # ===================================================================================================== head_name = "count/光照" cols_name = illum_types # ----------------------------------------------------------------------------------------------------- data_acc_illum_types = np.r_[data_acc_illum_types, np.mean(data_acc_illum_types, axis=0).reshape(1, -1)] data_loss_illum_types = np.r_[data_loss_illum_types, np.mean(data_loss_illum_types, axis=0).reshape(1, -1)] # ----------------------------------------------------------------------------------------------------- table_acc_illum_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_illum_types ) table_loss_illum_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_illum_types) with open("images/3_5_<table>_[{}]_[illum_types].txt".format(datatype), 'w') as f: f.write("\n\nacc\n") f.write(table_acc_illum_types) f.write("\n\nloss\n") f.write(table_loss_illum_types) # ----------------------------------------------------------------------------------------------------- plt.figure() plt.subplot(121); plt.title("acc") avg_acc = data_acc_illum_types[-1] plt.bar(np.arange(avg_acc.shape[0]), avg_acc ) plt.subplot(122); plt.title("loss") avg_loss = data_loss_illum_types[-1] plt.bar(np.arange(avg_loss.shape[0]), avg_loss) plt.savefig("images/3_5_<figure>_[{}]_[illum_types].png".format(datatype)) # ===================================================================================================== head_name = "count/位置" cols_name = list(map(str, positions)) # ----------------------------------------------------------------------------------------------------- data_acc_positions = np.r_[data_acc_positions, np.mean(data_acc_positions, axis=0).reshape(1, -1)] data_loss_positions = np.r_[data_loss_positions, np.mean(data_loss_positions, axis=0).reshape(1, -1)] # ----------------------------------------------------------------------------------------------------- table_acc_positions = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_positions ) table_loss_positions = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_positions) with open("images/3_5_<table>_[{}]_[positions].md".format(datatype), 'w') as f: f.write("\n\nacc\n") f.write(table_acc_positions) f.write("\n\nloss\n") f.write(table_loss_positions) # ----------------------------------------------------------------------------------------------------- plt.figure() plt.subplot(121); plt.title("acc") avg_acc = data_acc_positions[-1] plt.bar(np.arange(avg_acc.shape[0]), avg_acc ) plt.subplot(122); plt.title("loss") avg_loss = data_loss_positions[-1] plt.bar(np.arange(avg_loss.shape[0]), avg_loss) plt.savefig("images/3_5_<figure>_[{}]_[positions].png".format(datatype)) # ===================================================================================================== head_name = "count/眼镜" cols_name = list(map(str, glass_types)) # ----------------------------------------------------------------------------------------------------- data_acc_glass_types = np.r_[data_acc_glass_types, np.mean(data_acc_glass_types, axis=0).reshape(1, -1)] data_loss_glass_types = np.r_[data_loss_glass_types, np.mean(data_loss_glass_types, axis=0).reshape(1, -1)] # ----------------------------------------------------------------------------------------------------- table_acc_glass_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_acc_glass_types ) table_loss_glass_types = gen_markdown_table_2d(head_name, rows_name, cols_name, data_loss_glass_types) with open("images/3_5_<table>_[{}]_[glass_types].txt".format(datatype), 'w') as f: f.write("\n\nacc\n") f.write(table_acc_glass_types) f.write("\n\nloss\n") f.write(table_loss_glass_types) # ----------------------------------------------------------------------------------------------------- plt.figure() plt.subplot(121); plt.title("acc") avg_acc = data_acc_glass_types[-1] plt.bar(np.arange(avg_acc.shape[0]), avg_acc ) plt.subplot(122); plt.title("loss") avg_loss = data_loss_glass_types[-1] plt.bar(np.arange(avg_loss.shape[0]), avg_loss) plt.savefig("images/3_5_<figure>_[{}]_[glass_types].png".format(datatype)) return start_time = time.time(); elapsed_time = 0 for datatype in datatypes: usedChannels = [i for i in range(1, 26)] \ if datatype == "Multi" else "RGB" data_acc = np.zeros(H) data_loss = np.zeros(H) for i in range(len(splitcounts)): splitcount = splitcounts[i] configer = get_configer(datatype=datatype, splitcount=splitcount, usedChannels=usedChannels) elapsed_time += time.time() - start_time start_time = time.time() print("Main 3.2 [{}] [{}] {}... Elaped >>> {} min".\ format(configer.datatype, configer.splitmode, usedChannels, elapsed_time/60)) logpath = os.path.join(configer.logspath, configer.modelname) print(logpath) if os.path.exists(logpath): with open(os.path.join(logpath, 'test_log.txt'), 'r') as f: test_log = f.readlines()[0] data_acc[i], data_loss[i] = parse_log(test_log) print(test_log) else: train(configer) data_acc[i], data_loss[i] = test(configer) print("-------------------------------------------------") ## 保存数据 avg_acc = np.mean(data_acc, axis=0) avg_loss = np.mean(data_loss, axis=0) table_data_acc = np.r_[data_acc, avg_acc ] table_data_loss = np.r_[data_loss, avg_loss] table_data = np.r_[table_data_acc.reshape(1, -1), table_data_loss.reshape(1, -1)] np.savetxt("images/3_5_<data>_[{}].txt".format(datatype), table_data)
def train(configer): ## datasets trainset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'train', configer.usedChannels) validset = RecognizeDataset(configer.datapath, configer.datatype, configer.splitmode, 'valid', configer.usedChannels) trainloader = DataLoader(trainset, configer.batchsize, shuffle=True) validloader = DataLoader(validset, configer.batchsize, shuffle=False) ## model modelpath = os.path.join(configer.mdlspath, configer.modelname) + '.pkl' modeldir = '/'.join(modelpath.split('/')[:-1]) model = modeldict[configer.modelbase](configer.n_usedChannels, configer.n_class, configer.dsize[0]) if not os.path.exists(modeldir): os.makedirs(modeldir) torch.save(model.state_dict(), modelpath) else: model.load_state_dict(torch.load()) model=torch.load("init.pkl") #if configer.cuda and is_available(): model.cuda() #ArcMargin = ArcMarginProduct(128,configer.n_class) ## loss loss = nn.CrossEntropyLoss() ## optimizer params = model.parameters() #optimizer = optim.Adam(params, configer.lrbase, weight_decay=1e-3) optimizer = optim.Adam(params, configer.lrbase) ## learning rate scheduler scheduler = lr_scheduler.StepLR(optimizer, configer.stepsize, configer.gamma) ## log logpath = os.path.join(configer.logspath, configer.modelname) if not os.path.exists(logpath): os.makedirs(logpath) logger = SummaryWriter(logpath) ## initialize elapsed_time = 0; total_time = 0; start_time = 0 acc_train = 0. acc_valid = 0. loss_train = float('inf') loss_valid = float('inf') loss_valid_last = float('inf') ## start training for i_epoch in range(configer.n_epoch): if configer.cuda and is_available(): empty_cache() scheduler.step(i_epoch) acc_train = []; acc_valid = [] loss_train = []; loss_valid = [] model.train() start_time = time.time() for i_batch, (X, y) in enumerate(trainloader): # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # forward if configer.modelbase == 'recognize_mobilefacenet': raw_logits = model(X) y_pred_prob = ArcMargin(raw_logits, y) else: y_pred_prob = model(X) #y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # backward optimizer.zero_grad() loss_i.backward() optimizer.step() # time duration_time = time.time() - start_time start_time = time.time() elapsed_time += duration_time total_time = duration_time * configer.n_epoch * len(trainset) // configer.batchsize # log print_log = "{} || Elapsed: {:.4f}h | Left: {:.4f}h | FPS: {:4.2f} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || lr: {:.6f} | accuracy: {:2.2%}, loss: {:4.4f}".\ format(getTime(), elapsed_time/3600, (total_time - elapsed_time)/3600, configer.batchsize / duration_time, i_epoch, configer.n_epoch, i_batch, len(trainset) // configer.batchsize, scheduler.get_lr()[-1], acc_i, loss_i) ##print(print_log) loss_train += [loss_i.detach().cpu().numpy()] acc_train += [acc_i.cpu().numpy()] print('------------------------------------------------------------------------------------------------------------------') model.eval() for i_batch, (X, y) in enumerate(validloader): # get batch X = Variable(X.float()); y = Variable(y) if configer.cuda and is_available(): X = X.cuda(); y = y.cuda() # # forward if configer.modelbase == 'recognize_mobilefacenet': raw_logits = model(X) y_pred_prob = ArcMargin(raw_logits, y) else: y_pred_prob = model(X) #y_pred_prob = model(X) loss_i = loss(y_pred_prob, y) acc_i = accuracy(y_pred_prob, y) # log print_log = "{} || Epoch: [{:3d}]/[{:3d}] | Batch: [{:3d}]/[{:3d}] || accuracy: {:2.2%}, loss: {:4.4f}".\ format(getTime(), i_epoch, configer.n_epoch, i_batch, len(validset) // configer.batchsize, acc_i, loss_i) ##print(print_log) loss_valid += [loss_i.detach().cpu().numpy()] acc_valid += [acc_i.cpu().numpy()] print('------------------------------------------------------------------------------------------------------------------') loss_train = np.mean(np.array(loss_train)) acc_train = np.mean(np.array(acc_train)) loss_valid = np.mean(np.array(loss_valid)) acc_valid = np.mean(np.array(acc_valid)) print_log = "{} || Epoch: [{:3d}]/[{:3d}] || lr: {:.6f} || train | acc: {:2.2%}, loss: {:4.4f} || valid | acc: {:2.2%}, loss: {:4.4f}".\ format(getTime(), i_epoch, configer.n_epoch, scheduler.get_lr()[-1], acc_train, loss_train, acc_valid, loss_valid) print(print_log) logger.add_scalars('accuracy', {'train': acc_train, 'valid': acc_valid}, i_epoch) logger.add_scalars('logloss', {'train': loss_train, 'valid': loss_valid}, i_epoch) logger.add_scalar('lr', scheduler.get_lr()[-1], i_epoch) print('------------------------------------------------------------------------------------------------------------------') if loss_valid_last > loss_valid: loss_valid_last = loss_valid torch.save(model, modelpath) print_log = "{} || Epoch: [{:3d}]/[{:3d}] || Saved as {}".\ format(getTime(), i_epoch, configer.n_epoch, modelpath) print(print_log) print('==================================================================================================================')