def test(): # load std models # policy_log_std = torch.load('./model_pkl/policy_net_action_std_model_1.pkl') # transition_log_std = torch.load('./model_pkl/transition_net_state_std_model_1.pkl') # define actor/critic/discriminator net and optimizer policy = Policy(discrete_action_sections, discrete_state_sections) value = Value() discriminator = Discriminator() discriminator_criterion = nn.BCELoss() # load expert data dataset = ExpertDataSet(args.data_set_path) data_loader = data.DataLoader(dataset=dataset, batch_size=1, shuffle=False, num_workers=0) # load net models discriminator.load_state_dict( torch.load('./model_pkl/Discriminator_model_2.pkl')) policy.transition_net.load_state_dict( torch.load('./model_pkl/Transition_model_2.pkl')) policy.policy_net.load_state_dict( torch.load('./model_pkl/Policy_model_2.pkl')) value.load_state_dict(torch.load('./model_pkl/Value_model_2.pkl')) discrete_state_loss_list = [] continous_state_loss_list = [] action_loss_list = [] cnt = 0 for expert_state_batch, expert_action_batch, expert_next_state in data_loader: cnt += 1 expert_state_action = torch.cat( (expert_state_batch, expert_action_batch), dim=-1).type(FloatTensor) next_discrete_state, next_continuous_state, _ = policy.get_transition_net_state( expert_state_action) gen_next_state = torch.cat( (next_discrete_state.to(device), next_continuous_state.to(device)), dim=-1) loss_func = torch.nn.MSELoss() continous_state_loss = loss_func(gen_next_state[:, 132:], expert_next_state[:, 132:]) discrete_state_loss = hamming_loss( gen_next_state[:, :132], expert_next_state[:, :132].type(torch.LongTensor)) discrete_action, continuous_action, _ = policy.get_policy_net_action( expert_state_batch.type(FloatTensor)) gen_action = torch.FloatTensor(continuous_action) loss_func = torch.nn.MSELoss() action_loss = loss_func(gen_action, expert_action_batch) discrete_state_loss_list.append(discrete_state_loss) continous_state_loss_list.append(continous_state_loss.item()) action_loss_list.append(action_loss) print(sum(discrete_state_loss_list) / cnt) print(sum(continous_state_loss_list) / cnt)
def init_models(self): generator = Generator(self.config).to(self.config.device) generator.apply(weights_init) if self.config.generator_path is not None: generator.load_state_dict(torch.load(self.config.generator_path)) # print(generator) discriminator = Discriminator(self.config).to(self.config.device) discriminator.apply(weights_init) if self.config.discriminator_path is not None: discriminator.load_state_dict( torch.load(self.config.discriminator_path)) # print(discriminator) return discriminator, generator
def main(): # set torch and numpy seed for reproducibility torch.manual_seed(27) np.random.seed(27) # tensorboard writer writer = SummaryWriter(settings.TENSORBOARD_DIR) # makedir snapshot makedir(settings.CHECKPOINT_DIR) # enable cudnn torch.backends.cudnn.enabled = True # create segmentor network model_G = Segmentor(pretrained=settings.PRETRAINED, num_classes=settings.NUM_CLASSES, modality=settings.MODALITY) model_G.train() model_G.cuda() torch.backends.cudnn.benchmark = True # create discriminator network model_D = Discriminator(settings.NUM_CLASSES) model_D.train() model_D.cuda() # dataset and dataloader dataset = TrainDataset() dataloader = data.DataLoader(dataset, batch_size=settings.BATCH_SIZE, shuffle=True, num_workers=settings.NUM_WORKERS, pin_memory=True, drop_last=True) test_dataset = TestDataset(data_root=settings.DATA_ROOT_VAL, data_list=settings.DATA_LIST_VAL) test_dataloader = data.DataLoader(test_dataset, batch_size=1, shuffle=False, num_workers=settings.NUM_WORKERS, pin_memory=True) # optimizer for generator network (segmentor) optim_G = optim.SGD(model_G.optim_parameters(settings.LR), lr=settings.LR, momentum=settings.LR_MOMENTUM, weight_decay=settings.WEIGHT_DECAY) # lr scheduler for optimi_G lr_lambda_G = lambda epoch: (1 - epoch / settings.EPOCHS )**settings.LR_POLY_POWER lr_scheduler_G = optim.lr_scheduler.LambdaLR(optim_G, lr_lambda=lr_lambda_G) # optimizer for discriminator network optim_D = optim.Adam(model_D.parameters(), settings.LR_D) # lr scheduler for optimi_D lr_lambda_D = lambda epoch: (1 - epoch / settings.EPOCHS )**settings.LR_POLY_POWER lr_scheduler_D = optim.lr_scheduler.LambdaLR(optim_D, lr_lambda=lr_lambda_D) # losses ce_loss = CrossEntropyLoss2d( ignore_index=settings.IGNORE_LABEL) # to use for segmentor bce_loss = BCEWithLogitsLoss2d() # to use for discriminator # upsampling for the network output upsample = nn.Upsample(size=(settings.CROP_SIZE, settings.CROP_SIZE), mode='bilinear', align_corners=True) # # labels for adversarial training # pred_label = 0 # gt_label = 1 # load the model to resume training last_epoch = -1 if settings.RESUME_TRAIN: checkpoint = torch.load(settings.LAST_CHECKPOINT) model_G.load_state_dict(checkpoint['model_G_state_dict']) model_G.train() model_G.cuda() model_D.load_state_dict(checkpoint['model_D_state_dict']) model_D.train() model_D.cuda() optim_G.load_state_dict(checkpoint['optim_G_state_dict']) optim_D.load_state_dict(checkpoint['optim_D_state_dict']) lr_scheduler_G.load_state_dict(checkpoint['lr_scheduler_G_state_dict']) lr_scheduler_D.load_state_dict(checkpoint['lr_scheduler_D_state_dict']) last_epoch = checkpoint['epoch'] # purge the logs after the last_epoch writer = SummaryWriter(settings.TENSORBOARD_DIR, purge_step=(last_epoch + 1) * len(dataloader)) for epoch in range(last_epoch + 1, settings.EPOCHS + 1): train_one_epoch(model_G, model_D, optim_G, optim_D, dataloader, test_dataloader, epoch, upsample, ce_loss, bce_loss, writer, print_freq=5, eval_freq=settings.EVAL_FREQ) if epoch % settings.CHECKPOINT_FREQ == 0 and epoch != 0: save_checkpoint(epoch, model_G, model_D, optim_G, optim_D, lr_scheduler_G, lr_scheduler_D) # save the final model if epoch >= settings.EPOCHS: print('saving the final model') save_checkpoint(epoch, model_G, model_D, optim_G, optim_D, lr_scheduler_G, lr_scheduler_D) writer.close() lr_scheduler_G.step() lr_scheduler_D.step()
def run(args): # Get device device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # Define model logger.info(f"Loading Model of {args.model_name}...") with open(args.config) as f: config = yaml.load(f, Loader=yaml.Loader) hp.lambda_stft = config["lamda_stft"] hp.use_feature_map_loss = config["use_feature_map_loss"] if args.model_name == "melgan": model = MelGANGenerator( in_channels=config["in_channels"], out_channels=config["out_channels"], kernel_size=config["kernel_size"], channels=config["channels"], upsample_scales=config["upsample_scales"], stack_kernel_size=config["stack_kernel_size"], stacks=config["stacks"], use_weight_norm=config["use_weight_norm"], use_causal_conv=config["use_causal_conv"]).to(device) elif args.model_name == "hifigan": model = HiFiGANGenerator( resblock_kernel_sizes=config["resblock_kernel_sizes"], upsample_rates=config["upsample_rates"], upsample_initial_channel=config["upsample_initial_channel"], resblock_type=config["resblock_type"], upsample_kernel_sizes=config["upsample_kernel_sizes"], resblock_dilation_sizes=config["resblock_dilation_sizes"], transposedconv=config["transposedconv"], bias=config["bias"]).to(device) elif args.model_name == "multiband-hifigan": model = MultiBandHiFiGANGenerator( resblock_kernel_sizes=config["resblock_kernel_sizes"], upsample_rates=config["upsample_rates"], upsample_initial_channel=config["upsample_initial_channel"], resblock_type=config["resblock_type"], upsample_kernel_sizes=config["upsample_kernel_sizes"], resblock_dilation_sizes=config["resblock_dilation_sizes"], transposedconv=config["transposedconv"], bias=config["bias"]).to(device) elif args.model_name == "basis-melgan": basis_signal_weight = np.load( os.path.join("Basis-MelGAN-dataset", "basis_signal_weight.npy")) basis_signal_weight = torch.from_numpy(basis_signal_weight) model = BasisMelGANGenerator( basis_signal_weight=basis_signal_weight, L=config["L"], in_channels=config["in_channels"], out_channels=config["out_channels"], kernel_size=config["kernel_size"], channels=config["channels"], upsample_scales=config["upsample_scales"], stack_kernel_size=config["stack_kernel_size"], stacks=config["stacks"], use_weight_norm=config["use_weight_norm"], use_causal_conv=config["use_causal_conv"], transposedconv=config["transposedconv"]).to(device) else: raise Exception("no model find!") pqmf = None if config["multiband"] == True: logger.info("Define PQMF") pqmf = PQMF().to(device) logger.info(f"model is {str(model)}") discriminator = Discriminator().to(device) logger.info("Model Has Been Defined") num_param = get_param_num(model) logger.info(f'Number of TTS Parameters: {num_param}') # Optimizer and loss basis_signal_optimizer = None if not args.mixprecision: if args.model_name == "basis-melgan": optimizer = Adam(model.melgan.parameters(), lr=args.learning_rate, eps=1.0e-6, weight_decay=0.0) # freeze basis signal layer basis_signal_optimizer = Adam(model.basis_signal.parameters()) else: optimizer = Adam(model.parameters(), lr=args.learning_rate, eps=1.0e-6, weight_decay=0.0) discriminator_optimizer = Adam(discriminator.parameters(), lr=args.learning_rate_discriminator, eps=1.0e-6, weight_decay=0.0) else: if args.model_name == "basis-melgan": raise Exception("basis melgan don't support amp!") optimizer = apex.optimizers.FusedAdam(model.parameters(), lr=args.learning_rate) discriminator_optimizer = apex.optimizers.FusedAdam( discriminator.parameters(), lr=args.learning_rate_discriminator) model, optimizer = amp.initialize(model, optimizer, opt_level="O1", keep_batchnorm_fp32=None) discriminator, discriminator_optimizer = amp.initialize( discriminator, discriminator_optimizer, opt_level="O1") logger.info("Start mix precision training...") if args.use_scheduler: scheduler = CosineAnnealingLR(optimizer, T_max=2500, eta_min=args.learning_rate / 10.) discriminator_scheduler = CosineAnnealingLR( discriminator_optimizer, T_max=2500, eta_min=args.learning_rate_discriminator / 10.) else: scheduler = None discriminator_scheduler = None vocoder_loss = Loss().to(device) logger.info("Defined Optimizer and Loss Function.") # Load checkpoint if exists os.makedirs(hp.checkpoint_path, exist_ok=True) current_checkpoint_path = str(datetime.now()).replace(" ", "-").replace( ":", "-").replace(".", "-") current_checkpoint_path = os.path.join(hp.checkpoint_path, current_checkpoint_path) try: checkpoint = torch.load(os.path.join(args.checkpoint_path), map_location=torch.device(device)) model.load_state_dict(checkpoint['model']) optimizer.load_state_dict(checkpoint['optimizer']) if 'discriminator' in checkpoint: logger.info("loading discriminator") discriminator.load_state_dict(checkpoint['discriminator']) discriminator_optimizer.load_state_dict( checkpoint['discriminator_optimizer']) os.makedirs(current_checkpoint_path, exist_ok=True) if args.mixprecision: amp.load_state_dict(checkpoint['amp']) logger.info("\n---Model Restored at Step %d---\n" % args.restore_step) except: logger.info("\n---Start New Training---\n") os.makedirs(current_checkpoint_path, exist_ok=True) # Init logger os.makedirs(hp.logger_path, exist_ok=True) current_logger_path = str(datetime.now()).replace(" ", "-").replace( ":", "-").replace(".", "-") writer = SummaryWriter( os.path.join(hp.tensorboard_path, current_logger_path)) current_logger_path = os.path.join(hp.logger_path, current_logger_path) os.makedirs(current_logger_path, exist_ok=True) # Get buffer if args.model_name != "basis-melgan": logger.info("Load data to buffer") buffer = load_data_to_buffer(args.audio_index_path, args.mel_index_path, logger, feature_savepath="features_train.bin") logger.info("Load valid data to buffer") valid_buffer = load_data_to_buffer( args.audio_index_valid_path, args.mel_index_valid_path, logger, feature_savepath="features_valid.bin") # Get dataset if args.model_name == "basis-melgan": dataset = WeightDataset(args.audio_index_path, args.mel_index_path, config["L"]) valid_dataset = WeightDataset(args.audio_index_valid_path, args.mel_index_valid_path, config["L"]) else: dataset = BufferDataset(buffer) valid_dataset = BufferDataset(valid_buffer) # Get Training Loader training_loader = DataLoader(dataset, batch_size=hp.batch_expand_size * hp.batch_size, shuffle=True, collate_fn=collate_fn_tensor, drop_last=True, num_workers=4, prefetch_factor=2, pin_memory=True) logger.info(f"Length of training loader is {len(training_loader)}") total_step = hp.epochs * len(training_loader) * hp.batch_expand_size # Define Some Information time_list = np.array([]) Start = time.perf_counter() # Training model = model.train() for epoch in range(hp.epochs): for i, batchs in enumerate(training_loader): # real batch start here for j, db in enumerate(batchs): current_step = i * hp.batch_expand_size + j + args.restore_step + epoch * len( training_loader) * hp.batch_expand_size + 1 # Get Data clock_1_s = time.perf_counter() mel = db["mel"].float().to(device) wav = db["wav"].float().to(device) mel = mel.contiguous().transpose(1, 2) weight = None if "weight" in db: weight = db["weight"].float().to(device) clock_1_e = time.perf_counter() time_used_1 = round(clock_1_e - clock_1_s, 5) # Training clock_2_s = time.perf_counter() time_list = trainer( model, discriminator, optimizer, discriminator_optimizer, scheduler, discriminator_scheduler, vocoder_loss, mel, wav, epoch, current_step, total_step, time_list, Start, current_checkpoint_path, current_logger_path, writer, weight=weight, basis_signal_optimizer=basis_signal_optimizer, pqmf=pqmf, mixprecision=args.mixprecision) clock_2_e = time.perf_counter() time_used_2 = round(clock_2_e - clock_2_s, 5) if current_step % hp.valid_step == 0: logger.info("Start valid...") valid_loader = DataLoader( valid_dataset, batch_size=1, shuffle=True, collate_fn=collate_fn_tensor_valid, num_workers=0) valid_loss_all = 0. for ii, valid_batch in enumerate(valid_loader): valid_mel = valid_batch["mel"].float().to(device) valid_mel = valid_mel.contiguous().transpose(1, 2) valid_wav = valid_batch["wav"].float().to(device) with torch.no_grad(): if args.model_name == "basis-melgan": valid_est_source, _ = model(valid_mel) else: valid_est_source = model(valid_mel) valid_stft_loss, _ = vocoder_loss(valid_est_source, valid_wav, pqmf=pqmf) valid_loss_all += valid_stft_loss.item() if ii == hp.valid_num: break writer.add_scalar('valid_stft_loss', valid_loss_all / float(hp.valid_num), global_step=current_step) writer.export_scalars_to_json(os.path.join("all_scalars.json")) writer.close() return
gv2_model_path = "/home/nhli/PycharmProj/ReIDGAN_/workdir/triplet-gv2/epoch-2000/save-fea-1999" save_path = "/home/nhli/PycharmProj/ReIDGAN_/workdir/triplet-gv2/" log_path = None # build graph feature_extractor = Inceptionv2() dis = Discriminator() if gv2_model_path is not None: fea_dict = torch.load(gv2_model_path) # fea_dict.pop('classifier.weight') # fea_dict.pop('classifier.bias') # fea_dict.pop('criterion2.center_feature') # fea_dict.pop('criterion2.all_labels') feature_extractor.load_state_dict(fea_dict) if dis_model_path is not None: dis.load_state_dict(torch.load(dis_model_path)) if is_cuda: feature_extractor.cuda() dis.cuda() # input pipeline data_iter = DataProvider(batch_size, is_cuda=is_cuda) # summary writer if log_path: writer = SummaryWriter(log_path, 'comment test') else: writer = None # opt
]) dataset = Dataset('c:/DATASETS/celebA/data.txt', 'c:/DATASETS/celebA/img_align_celeba', transform) # logs_idx = len(glob.glob('logs/*')) # depth_start = 0 # epoch_start = 0 # global_idx = 0 logs_idx = 0 saves = glob.glob(f'logs/{logs_idx}/*.pt') saves.sort(key=os.path.getmtime) checkpoint = torch.load(saves[-1]) generator.load_state_dict(checkpoint['generator_state_dict']) generator.train() discriminator.load_state_dict(checkpoint['discriminator_state_dict']) discriminator.train() g_optimizer.load_state_dict(checkpoint['g_optimizer_state_dict']) d_optimizer.load_state_dict(checkpoint['d_optimizer_state_dict']) depth_start = checkpoint['depth'] epoch_start = checkpoint['epoch'] global_idx = checkpoint['global_idx'] writer = tensorboard.SummaryWriter(log_dir=f'logs/{logs_idx}') for depth, (batch_size, epoch_size) in enumerate(tqdm(zip(batch_sizes[depth_start:], epoch_sizes[depth_start:]), initial=depth_start, total=len(epoch_sizes)), start=depth_start):
class Trial: def __init__(self, data_dir: str = './dataset', log_dir: str = './logs', device: str = "cuda:0", batch_size: int = 2, init_lr: float = 0.5, G_lr: float = 0.0004, D_lr: float = 0.0008, level: str = "O1", patch: bool = False, init_training_epoch: int = 10, train_epoch: int = 10, optim_type: str = "ADAM", pin_memory: bool = True, grad_set_to_none: bool = True): # self.config = config self.data_dir = data_dir self.dataset = Dataset(root=data_dir + "/Shinkai", style_transform=tr.transform, smooth_transform=tr.transform) self.pin_memory = pin_memory self.batch_size = batch_size self.dataloader = DataLoader(self.dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=pin_memory) self.device = torch.device( device) if torch.cuda.is_available() else torch.device('cpu') self.G = Generator().to(self.device) self.patch = patch if self.patch: self.D = PatchDiscriminator().to(self.device) else: self.D = Discriminator().to(self.device) self.init_model_weights() self.optimizer_G = GANOptimizer(optim_type, self.G.parameters(), lr=G_lr, betas=(0.5, 0.999), amsgrad=False) self.optimizer_D = GANOptimizer(optim_type, self.D.parameters(), lr=D_lr, betas=(0.5, 0.999), amsgrad=True) self.loss = Loss(device=self.device).to(self.device) self.init_lr = init_lr self.G_lr = G_lr self.D_lr = D_lr self.grad_set_to_none = grad_set_to_none self.writer = tensorboard.SummaryWriter(log_dir=log_dir) self.init_train_epoch = init_training_epoch self.train_epoch = train_epoch self.init_time = None self.level = level if self.level != "O0" and device != "cpu": self.fp16 = True [self.G, self.D], [self.optimizer_G, self.optimizer_D ] = amp.initialize([self.G, self.D], [self.optimizer_G, self.optimizer_D], opt_level=self.level) else: self.fp16 = False def init_model_weights(self): self.G.apply(weights_init) self.D.apply(weights_init) @classmethod def from_config(cls): pass def init_train(self, con_weight: float = 1.0): test_img = self.get_test_image() meter = AverageMeter("Loss") self.writer.flush() lr_scheduler = OneCycleLR(self.optimizer_G, max_lr=0.9999, steps_per_epoch=len(self.dataloader), epochs=self.init_train_epoch) for g in self.optimizer_G.param_groups: g['lr'] = self.init_lr for epoch in tqdm(range(self.init_train_epoch)): meter.reset() for i, (style, smooth, train) in enumerate(self.dataloader, 0): # train = transform(test_img).unsqueeze(0) self.G.zero_grad(set_to_none=self.grad_set_to_none) train = train.to(self.device) generator_output = self.G(train) # content_loss = loss.reconstruction_loss(generator_output, train) * con_weight content_loss = self.loss.content_loss(generator_output, train) * con_weight # content_loss = F.mse_loss(train, generator_output) * con_weight content_loss.backward() self.optimizer_G.step() lr_scheduler.step() meter.update(content_loss.detach()) self.writer.add_scalar(f"Loss : {self.init_time}", meter.sum.item(), epoch) self.write_weights(epoch + 1, write_D=False) self.eval_image(epoch, f'{self.init_time} reconstructed img', test_img) for g in self.optimizer_G.param_groups: g['lr'] = self.G_lr # self.save_trial(self.init_train_epoch, "init") def eval_image(self, epoch: int, caption, img): """Feeds in one single image to process and save.""" self.G.eval() styled_test_img = tr.transform(img).unsqueeze(0).to(self.device) with torch.no_grad(): styled_test_img = self.G(styled_test_img) styled_test_img = styled_test_img.to('cpu').squeeze() self.write_image(styled_test_img, caption, epoch + 1) self.writer.flush() self.G.train() def write_image(self, image: torch.Tensor, img_caption: str = "sample_image", step: int = 0): image = torch.clip(tr.inv_norm(image).to(torch.float), 0, 1) # [-1, 1] -> [0, 1] image *= 255. # [0, 1] -> [0, 255] image = image.permute(1, 2, 0).to(dtype=torch.uint8) self.writer.add_image(img_caption, image, step, dataformats='HWC') self.writer.flush() def write_weights(self, epoch: int, write_D=True, write_G=True): if write_D: for name, weight in self.D.named_parameters(): if 'depthwise' in name or 'pointwise' in name: self.writer.add_histogram( f"Discriminator {name} {self.init_time}", weight, epoch) self.writer.add_histogram( f"Discriminator {name}.grad {self.init_time}", weight.grad, epoch) self.writer.flush() if write_G: for name, weight in self.G.named_parameters(): self.writer.add_histogram(f"Generator {name} {self.init_time}", weight, epoch) self.writer.add_histogram( f"Generator {name}.grad {self.init_time}", weight.grad, epoch) self.writer.flush() def train_1( self, adv_weight: float = 300., con_weight: float = 1.5, gra_weight: float = 3., col_weight: float = 10., ): test_img_dir = Path( self.data_dir).joinpath('test/test_photo256').resolve() test_img_dir = random.choice(list(test_img_dir.glob('**/*'))) test_img = Image.open(test_img_dir) self.writer.add_image(f'test image {self.init_time}', np.asarray(test_img), dataformats='HWC') self.writer.flush() for epoch in tqdm(range(self.train_epoch)): for i, (style, smooth, train) in enumerate(self.dataloader, 0): self.D.zero_grad() style = style.to(self.device) smooth = smooth.to(self.device) train = train.to(self.device) # style image to discriminator(Not Gram Matrix Loss) style_loss_value = self.D(style).view(-1) generator_output = self.G(train) # generated image to discriminator real_output = self.D(generator_output.detach()).view(-1) # greyscale_output = D(transforms.functional.rgb_to_grayscale(train, num_output_channels=3)).view(-1) #greyscale adversarial loss gray_train = tr.inv_gray_transform(train) greyscale_output = self.D(gray_train).view(-1) smoothed_loss = self.D(smooth).view(-1) # smoothed image loss # loss_D_real = adversarial_loss(output, label) dis_adv_loss = adv_weight * ( torch.pow(style_loss_value - 1, 2).mean() + torch.pow(real_output, 2).mean()) dis_gray_loss = torch.pow(greyscale_output, 2).mean() dis_edge_loss = torch.pow(smoothed_loss, 2).mean() discriminator_loss = dis_adv_loss + dis_gray_loss + dis_edge_loss discriminator_loss.backward() self.optimizer_D.step() if i % 200 == 0 and i != 0: self.writer.add_scalars( f'{self.init_time} Discriminator losses', { 'adversarial loss': dis_adv_loss.item(), 'grayscale loss': dis_gray_loss.item(), 'edge loss': dis_edge_loss.item() }, i + epoch * len(self.dataloader)) self.writer.flush() real_output = self.D(generator_output).view(-1) per_loss = self.loss.perceptual_loss( train, generator_output) # loss for G style_loss = self.loss.style_loss(generator_output, style) content_loss = self.loss.content_loss(generator_output, train) recon_loss = self.loss.reconstruction_loss( generator_output, train) tv_loss = self.loss.tv_loss(generator_output) ''' print('[%d/%d][%d/%d]\tLoss_D: %.4f\tLoss_G: %.4f\tD(x): %.4f\tD(G(z)): %.4f / %.4f' % (epoch, num_epoch, i, len(data_loader), loss_D.item(), loss_G.item(), D_x, D_G_z1, D_G_z2))''' self.G.zero_grad() gen_adv_loss = adv_weight * torch.pow(real_output - 1, 2).mean() gen_con_loss = con_weight * content_loss gen_sty_loss = gra_weight * style_loss gen_rec_loss = col_weight * recon_loss gen_per_loss = per_loss gen_tv_loss = tv_loss generator_loss = gen_adv_loss + gen_con_loss + gen_sty_loss + gen_rec_loss + gen_per_loss generator_loss.backward() self.optimizer_G.step() if i % 200 == 0 and i != 0: self.writer.add_scalars( f'generator losses {self.init_time}', { 'adversarial loss': gen_adv_loss.item(), 'content loss': gen_con_loss.item(), 'style loss': gen_sty_loss.item(), 'reconstruction loss': gen_rec_loss.item(), 'perceptual loss': gen_per_loss.item() }, i + epoch * len(self.dataloader)) self.writer.flush() self.write_weights(epoch + 1) self.eval_image(epoch, f'{self.init_time} style img', test_img) def train_2(self, adv_weight: float = 1.0, threshold: float = 3., G_train_iter: int = 1, D_train_iter: int = 1 ): # if threshold is 0., set to half of adversarial loss test_img_dir = Path(self.data_dir).joinpath('test', 'test_photo256') test_img_dir = random.choice(list(test_img_dir.glob('**/*'))) test_img = Image.open(test_img_dir) if self.init_time is None: self.init_time = datetime.datetime.now().strftime("%H:%M") self.writer.add_image(f'sample_image {self.init_time}', np.asarray(test_img), dataformats='HWC') self.writer.flush() perception_weight = 0. keep_constant = False for epoch in tqdm(range(self.train_epoch)): total_dis_loss = 0. for i, (style, smooth, train) in enumerate(self.dataloader, 0): self.D.zero_grad() train = train.to(self.device) style = style.to(self.device) # smooth = smooth.to(device) for _ in range(D_train_iter): style_loss_value = self.D(style).view(-1) generator_output = self.G(train) real_output = self.D(generator_output.detach()).view(-1) dis_adv_loss = adv_weight * \ (torch.pow(style_loss_value - 1, 2).mean() + torch.pow(real_output, 2).mean()) total_dis_loss += dis_adv_loss.item() dis_adv_loss.backward() self.optimizer_D.step() self.G.zero_grad() for _ in range(G_train_iter): generator_output = self.G(train) real_output = self.D(generator_output).view(-1) per_loss = perception_weight * \ self.loss.perceptual_loss(train, generator_output) gen_adv_loss = adv_weight * torch.pow(real_output - 1, 2).mean() gen_loss = gen_adv_loss + per_loss gen_loss.backward() self.optimizer_G.step() if i % 200 == 0 and i != 0: self.writer.add_scalars( f'generator losses {self.init_time}', { 'adversarial loss': dis_adv_loss.item(), 'Generator adversarial loss': gen_adv_loss.item(), 'perceptual loss': per_loss.item() }, i + epoch * len(self.dataloader)) self.writer.flush() if total_dis_loss > threshold and not keep_constant: perception_weight += 0.05 else: keep_constant = True self.writer.add_scalar( f'total discriminator loss {self.init_time}', total_dis_loss, i + epoch * len(self.dataloader)) self.write_weights() self.G.eval() styled_test_img = tr.transform(test_img).unsqueeze(0).to( self.device) with torch.no_grad(): styled_test_img = self.G(styled_test_img) styled_test_img = styled_test_img.to('cpu').squeeze() self.write_image(styled_test_img, f'styled image {self.init_time}', epoch + 1) self.G.train() def __call__(self): self.init_train() self.train_1() def save_trial(self, epoch: int, train_type: str): save_dir = Path(f"{train_type}_{self.level}.pt") training_details = { "epoch": epoch, "gen": { "gen_state_dict": self.G.state_dict(), "optim_G_state_dict": self.optimizer_G.state_dict() }, "dis": { "dis_state_dict": self.D.state_dict(), "optim_D_state_dict": self.optimizer_D.state_dict() } } if self.fp16: training_details["amp"] = amp.state_dict() torch.save(training_details, save_dir.as_posix()) def load_trial(self, dir: Path): assert dir.is_file(), "No such directory" assert dir.suffix == ".pt", "Filetype not compatible" state_dicts = torch.load(dir.as_posix()) self.G.load_state_dict(state_dicts["gen"]["gen_state_dict"]) self.optimizer_G.load_state_dict( state_dicts["gen"]["optim_G_state_dict"]) self.D.load_state_dict(state_dicts["dis"]["dis_state_dict"]) self.optimizer_D.load_state_dict( state_dicts["dis"]["optim_D_state_dict"]) if self.fp16: amp.load_state_dict(state_dicts["amp"]) typer.echo("Loaded Weights") def Generator_NOGAN(self, epochs: int = 1, style_weight: float = 20., content_weight: float = 1.2, recon_weight: float = 10., tv_weight: float = 1e-6, loss: List[str] = ['content_loss']): """Training Generator in NOGAN manner (Feature Loss only).""" for g in self.optimizer_G.param_groups: g['lr'] = self.G_lr test_img = self.get_test_image() max_lr = self.G_lr * 10. lr_scheduler = OneCycleLR(self.optimizer_G, max_lr=max_lr, steps_per_epoch=len(self.dataloader), epochs=epochs) meter = LossMeters(*loss) total_loss_arr = np.array([]) for epoch in tqdm(range(epochs)): total_losses = 0 meter.reset() for i, (style, smooth, train) in enumerate(self.dataloader, 0): # train = transform(test_img).unsqueeze(0) self.G.zero_grad(set_to_none=self.grad_set_to_none) train = train.to(self.device) generator_output = self.G(train) if 'style_loss' in loss: style = style.to(self.device) style_loss = self.loss.style_loss(generator_output, style) * style_weight else: style_loss = 0. if 'content_loss' in loss: content_loss = self.loss.content_loss( generator_output, train) * content_weight else: content_loss = 0. if 'recon_loss' in loss: recon_loss = self.loss.reconstruction_loss( generator_output, train) * recon_weight else: recon_loss = 0. if 'tv_loss' in loss: tv_loss = self.loss.tv_loss(generator_output) * tv_weight else: tv_loss = 0. total_loss = content_loss + tv_loss + recon_loss + style_loss if self.fp16: with amp.scale_loss(total_loss, self.optimizer_G) as scaled_loss: scaled_loss.backward() else: total_loss.backward() self.optimizer_G.step() lr_scheduler.step() total_losses += total_loss.detach() loss_dict = { 'content_loss': content_loss, 'style_loss': style_loss, 'recon_loss': recon_loss, 'tv_loss': tv_loss } losses = [loss_dict[loss_type].detach() for loss_type in loss] meter.update(*losses) total_loss_arr = np.append(total_loss_arr, total_losses.item()) self.writer.add_scalars(f'{self.init_time} NOGAN generator losses', meter.as_dict('sum'), epoch) self.write_weights(epoch + 1, write_D=False) self.eval_image(epoch, f'{self.init_time} reconstructed img', test_img) if epoch > 2: fig = plt.figure(figsize=(8, 8)) X = np.arange(len(total_loss_arr)) Y = np.gradient(total_loss_arr) plt.plot(X, Y) thresh = -1.0 plt.axhline(thresh, c='r') plt.title(f"{self.init_time}") self.writer.add_figure(f"{self.init_time}", fig, epoch) if Y[-1] > thresh: break self.save_trial(epoch, f'G_NG_{self.init_time}') def Discriminator_NOGAN( self, epochs: int = 3, adv_weight: float = 1.0, edge_weight: float = 1.0, loss: List[str] = ['real_adv_loss', 'fake_adv_loss', 'gray_loss']): """https://discuss.pytorch.org/t/scheduling-batch-size-in-dataloader/46443/2""" for g in self.optimizer_D.param_groups: g['lr'] = self.D_lr max_lr = self.D_lr * 10. lr_scheduler = OneCycleLR(self.optimizer_D, max_lr=max_lr, steps_per_epoch=len(self.dataloader), epochs=epochs) meter = LossMeters(*loss) total_loss_arr = np.array([]) if self.init_time is None: self.init_time = datetime.datetime.now().strftime("%H:%M") for epoch in tqdm(range(epochs)): meter.reset() for i, (style, smooth, train) in enumerate(self.dataloader, 0): # train = transform(test_img).unsqueeze(0) self.D.zero_grad(set_to_none=self.grad_set_to_none) train = train.to(self.device) style = style.to(self.device) generator_output = self.G(train) real_adv_loss = self.D(style).view(-1) fake_adv_loss = self.D(generator_output.detach()).view(-1) real_adv_loss = torch.pow(real_adv_loss - 1, 2).mean() * 1.7 * adv_weight fake_adv_loss = torch.pow(fake_adv_loss, 2).mean() * 1.7 * adv_weight gray_train = tr.inv_gray_transform(style) greyscale_output = self.D(gray_train).view(-1) gray_loss = torch.pow(greyscale_output, 2).mean() * 1.7 * adv_weight "According to AnimeGANv2 implementation, every loss is scaled by individual weights and then scaled with adv_weight" "https://github.com/TachibanaYoshino/AnimeGANv2/blob/5946b6afcca5fc28518b75a763c0f561ff5ce3d6/tools/ops.py#L217" total_loss = real_adv_loss + fake_adv_loss + gray_loss if self.fp16: with amp.scale_loss(total_loss, self.optimizer_D) as scaled_loss: scaled_loss.backward() else: total_loss.backward() self.optimizer_D.step() lr_scheduler.step() loss_dict = { 'real_adv_loss': real_adv_loss, 'fake_adv_loss': fake_adv_loss, 'gray_loss': gray_loss } losses = [loss_dict[loss_type].detach() for loss_type in loss] meter.update(*losses) self.writer.add_scalars( f'{self.init_time} NOGAN discriminator loss', meter.as_dict('sum'), epoch) self.writer.flush() if epoch > 2: fig = plt.figure(figsize=(8, 8)) X = np.arange(len(total_loss_arr)) Y = np.gradient(total_loss_arr) plt.plot(X, Y) thresh = -1.0 plt.axhline(thresh, c='r') plt.title(f"{self.init_time}") self.writer.add_figure(f"{self.init_time}", fig, epoch) if Y[-1] > thresh: break def GAN_NOGAN( self, epochs: int = 1, GAN_G_lr: float = 0.00008, GAN_D_lr: float = 0.000016, D_loss: List[str] = [ "real_adv_loss", "fake_adv_loss", "gray_loss", "edge_loss" ], adv_weight: float = 300., edge_weight: float = 0.1, G_loss: List[str] = [ "adv_loss", "content_loss", "style_loss", "recon_loss" ], style_weight: float = 20., content_weight: float = 1.2, recon_weight: float = 10., tv_weight: float = 1e-6, ): test_img = self.get_test_image() dis_meter = LossMeters(*D_loss) gen_meter = LossMeters(*G_loss) for g in self.optimizer_G.param_groups: g['lr'] = GAN_G_lr for g in self.optimizer_D.param_groups: g['lr'] = GAN_D_lr update_duration = len(self.dataloader) // 20 for epoch in tqdm(range(epochs)): G_loss_arr = np.array([]) dis_meter.reset() count = 0 for i, (style, smooth, train) in enumerate(self.dataloader, 0): self.D.zero_grad(set_to_none=self.grad_set_to_none) train = train.to(self.device) style = style.to(self.device) smooth = smooth.to(self.device) generator_output = self.G(train) real_adv_loss = self.D(style).view(-1) fake_adv_loss = self.D(generator_output.detach()).view(-1) G_adv_loss = self.D(generator_output).view(-1) gray_train = tr.inv_gray_transform(style) grayscale_output = self.D(gray_train).view(-1) gray_smooth_data = tr.inv_gray_transform(smooth) smoothed_output = self.D(smooth).view(-1) real_adv_loss = torch.square(real_adv_loss - 1.).mean() * 1.7 * adv_weight fake_adv_loss = torch.square( fake_adv_loss).mean() * 1.7 * adv_weight gray_loss = torch.square( grayscale_output).mean() * 1.7 * adv_weight edge_loss = torch.square( smoothed_output).mean() * 1.0 * adv_weight total_D_loss = real_adv_loss + fake_adv_loss + gray_loss + edge_loss total_D_loss.backward() self.optimizer_D.step() D_loss_dict = { 'real_adv_loss': real_adv_loss, 'fake_adv_loss': fake_adv_loss, 'gray_loss': gray_loss, 'edge_loss': edge_loss } loss = list(D_loss_dict.values()) dis_meter.update(*loss) if i % update_duration == 0 and i != 0: self.writer.add_scalars(f'{self.init_time} NOGAN Dis loss', dis_meter.as_dict('val'), i + epoch * len(self.dataloader)) self.writer.flush() self.G.zero_grad(set_to_none=self.grad_set_to_none) G_adv_loss = torch.square(G_adv_loss - 1.).mean() * adv_weight if 'style_loss' in G_loss: style_loss = self.loss.style_loss(generator_output, style) * style_weight else: style_loss = 0. if 'content_loss' in G_loss: content_loss = self.loss.content_loss( generator_output, train) * content_weight else: content_loss = 0. if 'recon_loss' in G_loss: recon_loss = self.loss.reconstruction_loss( generator_output, train) * recon_weight else: recon_loss = 0. if 'tv_loss' in G_loss: tv_loss = self.loss.tv_loss(generator_output) * tv_weight else: tv_loss = 0. total_G_loss = G_adv_loss + content_loss + tv_loss + recon_loss + style_loss total_G_loss.backward() self.optimizer_G.step() G_loss_dict = { 'adv_loss': G_adv_loss, 'content_loss': content_loss, 'style_loss': style_loss, 'recon_loss': recon_loss, 'tv_loss': tv_loss } losses = [ G_loss_dict[loss_type].detach() for loss_type in G_loss ] gen_meter.update(*losses) if i % update_duration == 0 and i != 0: self.writer.add_scalars(f'{self.init_time} NOGAN Gen loss', gen_meter.as_dict('val'), i + epoch * len(self.dataloader)) self.writer.flush() G_loss_arr = np.append(G_loss_arr, G_adv_loss.item()) self.eval_image(i + epoch * len(self.dataloader), f'{self.init_time} reconstructed img', test_img) self.save_trial(epoch, f'GAN_NG_{self.init_time}') def get_test_image(self): """Get random test image.""" test_img_dir = Path(self.data_dir).joinpath('test/test_photo256') test_img_dir = random.choice(list(test_img_dir.glob('**/*'))) test_img = Image.open(test_img_dir) self.init_time = datetime.datetime.now().strftime("%H:%M") self.writer.add_image(f'{self.init_time} sample_image', np.asarray(test_img), dataformats='HWC') self.writer.flush() return test_img
def main(args=args): dataset_base_path = path.join(args.base_path, "dataset", "celeba") image_base_path = path.join(dataset_base_path, "img_align_celeba") split_dataset_path = path.join(dataset_base_path, "Eval", "list_eval_partition.txt") with open(split_dataset_path, "r") as f: split_annotation = f.read().splitlines() # create the data name list for train,test and valid train_data_name_list = [] test_data_name_list = [] valid_data_name_list = [] for item in split_annotation: item = item.split(" ") if item[1] == '0': train_data_name_list.append(item[0]) elif item[1] == '1': valid_data_name_list.append(item[0]) else: test_data_name_list.append(item[0]) attribute_annotation_dict = None if args.need_label: attribute_annotation_path = path.join(dataset_base_path, "Anno", "list_attr_celeba.txt") with open(attribute_annotation_path, "r") as f: attribute_annotation = f.read().splitlines() attribute_annotation = attribute_annotation[2:] attribute_annotation_dict = {} for item in attribute_annotation: img_name, attribute = item.split(" ", 1) attribute = tuple([eval(attr) for attr in attribute.split(" ") if attr != ""]) assert len(attribute) == 40, "the attribute of item {} is not equal to 40".format(img_name) attribute_annotation_dict[img_name] = attribute discriminator = Discriminator(num_channel=args.num_channel, num_feature=args.dnf, data_parallel=args.data_parallel).cuda() generator = Generator(latent_dim=args.latent_dim, num_feature=args.gnf, num_channel=args.num_channel, data_parallel=args.data_parallel).cuda() input("Begin the {} time's training, the train dataset has {} images and the valid has {} images".format( args.train_time, len(train_data_name_list), len(valid_data_name_list))) d_optimizer = torch.optim.Adam(discriminator.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) g_optimizer = torch.optim.Adam(generator.parameters(), lr=args.lr, betas=(args.beta1, 0.999)) d_scheduler = ExponentialLR(d_optimizer, gamma=args.decay_lr) g_scheduler = ExponentialLR(g_optimizer, gamma=args.decay_lr) writer_log_dir = "{}/DCGAN/runs/train_time:{}".format(args.base_path, args.train_time) # Here we implement the resume part if args.resume: if os.path.isfile(args.resume): print("=> loading checkpoint '{}'".format(args.resume)) checkpoint = torch.load(args.resume) if not args.not_resume_arg: args = checkpoint['args'] args.start_epoch = checkpoint['epoch'] discriminator.load_state_dict(checkpoint["discriminator_state_dict"]) generator.load_state_dict(checkpoint["generator_state_dict"]) d_optimizer.load_state_dict(checkpoint['discriminator_optimizer']) g_optimizer.load_state_dict(checkpoint['generator_optimizer']) print("=> loaded checkpoint '{}' (epoch {})" .format(args.resume, checkpoint['epoch'])) else: raise FileNotFoundError("Checkpoint Resume File {} Not Found".format(args.resume)) else: if os.path.exists(writer_log_dir): flag = input("DCGAN train_time:{} will be removed, input yes to continue:".format( args.train_time)) if flag == "yes": shutil.rmtree(writer_log_dir, ignore_errors=True) writer = SummaryWriter(log_dir=writer_log_dir) # Here we just use the train dset in training train_dset = CelebADataset(base_path=image_base_path, data_name_list=train_data_name_list, image_size=args.image_size, label_dict=attribute_annotation_dict) train_dloader = DataLoader(dataset=train_dset, batch_size=args.batch_size, shuffle=True, num_workers=args.workers, pin_memory=True) criterion = nn.BCELoss() for epoch in range(args.start_epoch, args.epochs): train(train_dloader, generator, discriminator, g_optimizer, d_optimizer, criterion, writer, epoch) # adjust lr d_scheduler.step() g_scheduler.step() # save parameters save_checkpoint({ 'epoch': epoch + 1, 'args': args, "discriminator_state_dict": discriminator.state_dict(), "generator_state_dict": generator.state_dict(), 'discriminator_optimizer': d_optimizer.state_dict(), 'generator_optimizer': g_optimizer.state_dict() })
class Trainer(nn.Module): def __init__(self, model_dir, g_optimizer, d_optimizer, lr, warmup, max_iters): super().__init__() self.model_dir = model_dir if not os.path.exists(f'checkpoints/{model_dir}'): os.makedirs(f'checkpoints/{model_dir}') self.logs_dir = f'checkpoints/{model_dir}/logs' if not os.path.exists(self.logs_dir): os.makedirs(self.logs_dir) self.writer = SummaryWriter(self.logs_dir) self.arcface = ArcFaceNet(50, 0.6, 'ir_se').cuda() self.arcface.eval() self.arcface.load_state_dict(torch.load( 'checkpoints/model_ir_se50.pth', map_location='cuda'), strict=False) self.mobiface = MobileFaceNet(512).cuda() self.mobiface.eval() self.mobiface.load_state_dict(torch.load( 'checkpoints/mobilefacenet.pth', map_location='cuda'), strict=False) self.generator = Generator().cuda() self.discriminator = Discriminator().cuda() self.adversarial_weight = 1 self.src_id_weight = 5 self.tgt_id_weight = 1 self.attributes_weight = 10 self.reconstruction_weight = 10 self.lr = lr self.warmup = warmup self.g_optimizer = g_optimizer(self.generator.parameters(), lr=lr, betas=(0, 0.999)) self.d_optimizer = d_optimizer(self.discriminator.parameters(), lr=lr, betas=(0, 0.999)) self.generator, self.g_optimizer = amp.initialize(self.generator, self.g_optimizer, opt_level="O1") self.discriminator, self.d_optimizer = amp.initialize( self.discriminator, self.d_optimizer, opt_level="O1") self._iter = nn.Parameter(torch.tensor(1), requires_grad=False) self.max_iters = max_iters if torch.cuda.is_available(): self.cuda() @property def iter(self): return self._iter.item() @property def device(self): return next(self.parameters()).device def adapt(self, args): device = self.device return [arg.to(device) for arg in args] def train_loop(self, dataloaders, eval_every, generate_every, save_every): for batch in tqdm(dataloaders['train']): torch.Tensor.add_(self._iter, 1) # generator step # if self.iter % 2 == 0: # self.adjust_lr(self.g_optimizer) g_losses = self.g_step(self.adapt(batch)) g_stats = self.get_opt_stats(self.g_optimizer, type='generator') self.write_logs(losses=g_losses, stats=g_stats, type='generator') # #discriminator step # if self.iter % 2 == 1: # self.adjust_lr(self.d_optimizer) d_losses = self.d_step(self.adapt(batch)) d_stats = self.get_opt_stats(self.d_optimizer, type='discriminator') self.write_logs(losses=d_losses, stats=d_stats, type='discriminator') if self.iter % eval_every == 0: discriminator_acc = self.evaluate_discriminator_accuracy( dataloaders['val']) identification_acc = self.evaluate_identification_similarity( dataloaders['val']) metrics = {**discriminator_acc, **identification_acc} self.write_logs(metrics=metrics) if self.iter % generate_every == 0: self.generate(*self.adapt(batch)) if self.iter % save_every == 0: self.save_discriminator() self.save_generator() def g_step(self, batch): self.generator.train() self.g_optimizer.zero_grad() L_adv, L_src_id, L_tgt_id, L_attr, L_rec, L_generator = self.g_loss( *batch) with amp.scale_loss(L_generator, self.g_optimizer) as scaled_loss: scaled_loss.backward() self.g_optimizer.step() losses = { 'adv': L_adv.item(), 'src_id': L_src_id.item(), 'tgt_id': L_tgt_id.item(), 'attributes': L_attr.item(), 'reconstruction': L_rec.item(), 'total_loss': L_generator.item() } return losses def d_step(self, batch): self.discriminator.train() self.d_optimizer.zero_grad() L_fake, L_real, L_discriminator = self.d_loss(*batch) with amp.scale_loss(L_discriminator, self.d_optimizer) as scaled_loss: scaled_loss.backward() self.d_optimizer.step() losses = { 'hinge_fake': L_fake.item(), 'hinge_real': L_real.item(), 'total_loss': L_discriminator.item() } return losses def g_loss(self, Xs, Xt, same_person): with torch.no_grad(): src_embed = self.arcface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) tgt_embed = self.arcface( F.interpolate(Xt[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) Y_hat, Xt_attr = self.generator(Xt, src_embed, return_attributes=True) Di = self.discriminator(Y_hat) L_adv = 0 for di in Di: L_adv += hinge_loss(di[0], True) fake_embed = self.arcface( F.interpolate(Y_hat[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) L_src_id = ( 1 - torch.cosine_similarity(src_embed, fake_embed, dim=1)).mean() L_tgt_id = ( 1 - torch.cosine_similarity(tgt_embed, fake_embed, dim=1)).mean() batch_size = Xs.shape[0] Y_hat_attr = self.generator.get_attr(Y_hat) L_attr = 0 for i in range(len(Xt_attr)): L_attr += torch.mean(torch.pow(Xt_attr[i] - Y_hat_attr[i], 2).reshape(batch_size, -1), dim=1).mean() L_attr /= 2.0 L_rec = torch.sum( 0.5 * torch.mean(torch.pow(Y_hat - Xt, 2).reshape(batch_size, -1), dim=1) * same_person) / (same_person.sum() + 1e-6) L_generator = (self.adversarial_weight * L_adv) + (self.src_id_weight * L_src_id) + ( self.tgt_id_weight * L_tgt_id) + (self.attributes_weight * L_attr) + ( self.reconstruction_weight * L_rec) return L_adv, L_src_id, L_tgt_id, L_attr, L_rec, L_generator def d_loss(self, Xs, Xt, same_person): with torch.no_grad(): src_embed = self.arcface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) Y_hat = self.generator(Xt, src_embed, return_attributes=False) fake_D = self.discriminator(Y_hat.detach()) L_fake = 0 for di in fake_D: L_fake += hinge_loss(di[0], False) real_D = self.discriminator(Xs) L_real = 0 for di in real_D: L_real += hinge_loss(di[0], True) L_discriminator = 0.5 * (L_real + L_fake) return L_fake, L_real, L_discriminator def evaluate_discriminator_accuracy(self, val_dataloader): real_acc = 0 fake_acc = 0 self.generator.eval() self.discriminator.eval() for batch in tqdm(val_dataloader): Xs, Xt, _ = self.adapt(batch) with torch.no_grad(): embed = self.arcface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) Y_hat = self.generator(Xt, embed, return_attributes=False) fake_D = self.discriminator(Y_hat) real_D = self.discriminator(Xs) fake_multiscale_acc = 0 for di in fake_D: fake_multiscale_acc += torch.mean((di[0] < 0).float()) fake_acc += fake_multiscale_acc / len(fake_D) real_multiscale_acc = 0 for di in real_D: real_multiscale_acc += torch.mean((di[0] > 0).float()) real_acc += real_multiscale_acc / len(real_D) self.generator.train() self.discriminator.train() metrics = { 'fake_acc': 100 * (fake_acc / len(val_dataloader)).item(), 'real_acc': 100 * (real_acc / len(val_dataloader)).item() } return metrics def evaluate_identification_similarity(self, val_dataloader): src_id_sim = 0 tgt_id_sim = 0 self.generator.eval() for batch in tqdm(val_dataloader): Xs, Xt, _ = self.adapt(batch) with torch.no_grad(): src_embed = self.arcface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) Y_hat = self.generator(Xt, src_embed, return_attributes=False) src_embed = self.mobiface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) tgt_embed = self.mobiface( F.interpolate(Xt[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) fake_embed = self.mobiface( F.interpolate(Y_hat[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) src_id_sim += (torch.cosine_similarity(src_embed, fake_embed, dim=1)).float().mean() tgt_id_sim += (torch.cosine_similarity(tgt_embed, fake_embed, dim=1)).float().mean() self.generator.train() metrics = { 'src_similarity': 100 * (src_id_sim / len(val_dataloader)).item(), 'tgt_similarity': 100 * (tgt_id_sim / len(val_dataloader)).item() } return metrics def generate(self, Xs, Xt, same_person): def get_grid_image(X): X = X[:8] X = torchvision.utils.make_grid(X.detach().cpu(), nrow=X.shape[0]) X = (X * 0.5 + 0.5) * 255 return X def make_image(Xs, Xt, Y_hat): Xs = get_grid_image(Xs) Xt = get_grid_image(Xt) Y_hat = get_grid_image(Y_hat) return torch.cat((Xs, Xt, Y_hat), dim=1).numpy() with torch.no_grad(): embed = self.arcface( F.interpolate(Xs[:, :, 19:237, 19:237], [112, 112], mode='bilinear', align_corners=True)) self.generator.eval() Y_hat = self.generator(Xt, embed, return_attributes=False) self.generator.train() image = make_image(Xs, Xt, Y_hat) if not os.path.exists(f'results/{self.model_dir}'): os.makedirs(f'results/{self.model_dir}') cv2.imwrite(f'results/{self.model_dir}/{self.iter}.jpg', image.transpose([1, 2, 0])) def get_opt_stats(self, optimizer, type=''): stats = {f'{type}_lr': optimizer.param_groups[0]['lr']} return stats def adjust_lr(self, optimizer): if self.iter <= self.warmup: lr = self.lr * self.iter / self.warmup else: lr = self.lr * (1 + cos(pi * (self.iter - self.warmup) / (self.max_iters - self.warmup))) / 2 for group in optimizer.param_groups: group['lr'] = lr return lr def write_logs(self, losses=None, metrics=None, stats=None, type='loss'): if losses: for name, value in losses.items(): self.writer.add_scalar(f'{type}/{name}', value, self.iter) if metrics: for name, value in metrics.items(): self.writer.add_scalar(f'metric/{name}', value, self.iter) if stats: for name, value in stats.items(): self.writer.add_scalar(f'stats/{name}', value, self.iter) def save_generator(self, max_checkpoints=100): checkpoints = glob.glob(f'{self.model_dir}/*.pt') if len(checkpoints) > max_checkpoints: os.remove(checkpoints[-1]) with open(f'checkpoints/{self.model_dir}/generator_{self.iter}.pt', 'wb') as f: torch.save(self.generator.state_dict(), f) def save_discriminator(self, max_checkpoints=100): checkpoints = glob.glob(f'{self.model_dir}/*.pt') if len(checkpoints) > max_checkpoints: os.remove(checkpoints[-1]) with open(f'checkpoints/{self.model_dir}/discriminator_{self.iter}.pt', 'wb') as f: torch.save(self.discriminator.state_dict(), f) def load_discriminator(self, path, load_last=True): if load_last: try: checkpoints = glob.glob(f'{path}/discriminator*.pt') path = max(checkpoints, key=os.path.getctime) except (ValueError): print(f'Directory is empty: {path}') try: self.discriminator.load_state_dict(torch.load(path)) self.cuda() except (FileNotFoundError): print(f'No such file: {path}') def load_generator(self, path, load_last=True): if load_last: try: checkpoints = glob.glob(f'{path}/generator*.pt') path = max(checkpoints, key=os.path.getctime) except (ValueError): print(f'Directory is empty: {path}') try: self.generator.load_state_dict(torch.load(path)) iter_str = ''.join(filter(lambda x: x.isdigit(), path)) self._iter = nn.Parameter(torch.tensor(int(iter_str)), requires_grad=False) self.cuda() except (FileNotFoundError): print(f'No such file: {path}')
def main(): ## load std models # policy_log_std = torch.load('./model_pkl/policy_net_action_std_model_1.pkl') # transition_log_std = torch.load('./model_pkl/transition_net_state_std_model_1.pkl') # load expert data print(args.data_set_path) dataset = ExpertDataSet(args.data_set_path) data_loader = data.DataLoader(dataset=dataset, batch_size=args.expert_batch_size, shuffle=True, num_workers=0) # define actor/critic/discriminator net and optimizer policy = Policy(onehot_action_sections, onehot_state_sections, state_0=dataset.state) value = Value() discriminator = Discriminator() optimizer_policy = torch.optim.Adam(policy.parameters(), lr=args.policy_lr) optimizer_value = torch.optim.Adam(value.parameters(), lr=args.value_lr) optimizer_discriminator = torch.optim.Adam(discriminator.parameters(), lr=args.discrim_lr) discriminator_criterion = nn.BCELoss() if write_scalar: writer = SummaryWriter(log_dir='runs/' + model_name) # load net models if load_model: discriminator.load_state_dict( torch.load('./model_pkl/Discriminator_model_' + model_name + '.pkl')) policy.transition_net.load_state_dict( torch.load('./model_pkl/Transition_model_' + model_name + '.pkl')) policy.policy_net.load_state_dict( torch.load('./model_pkl/Policy_model_' + model_name + '.pkl')) value.load_state_dict( torch.load('./model_pkl/Value_model_' + model_name + '.pkl')) policy.policy_net_action_std = torch.load( './model_pkl/Policy_net_action_std_model_' + model_name + '.pkl') policy.transition_net_state_std = torch.load( './model_pkl/Transition_net_state_std_model_' + model_name + '.pkl') print('############# start training ##############') # update discriminator num = 0 for ep in tqdm(range(args.training_epochs)): # collect data from environment for ppo update policy.train() value.train() discriminator.train() start_time = time.time() memory, n_trajs = policy.collect_samples( batch_size=args.sample_batch_size) # print('sample_data_time:{}'.format(time.time()-start_time)) batch = memory.sample() onehot_state = torch.cat(batch.onehot_state, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() multihot_state = torch.cat(batch.multihot_state, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() continuous_state = torch.cat(batch.continuous_state, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() onehot_action = torch.cat(batch.onehot_action, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() multihot_action = torch.cat(batch.multihot_action, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() continuous_action = torch.cat(batch.continuous_action, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() next_onehot_state = torch.cat(batch.next_onehot_state, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() next_multihot_state = torch.cat(batch.next_multihot_state, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() next_continuous_state = torch.cat( batch.next_continuous_state, dim=1).reshape(n_trajs * args.sample_traj_length, -1).detach() old_log_prob = torch.cat(batch.old_log_prob, dim=1).reshape( n_trajs * args.sample_traj_length, -1).detach() mask = torch.cat(batch.mask, dim=1).reshape(n_trajs * args.sample_traj_length, -1).detach() gen_state = torch.cat((onehot_state, multihot_state, continuous_state), dim=-1) gen_action = torch.cat( (onehot_action, multihot_action, continuous_action), dim=-1) if ep % 1 == 0: # if (d_slow_flag and ep % 50 == 0) or (not d_slow_flag and ep % 1 == 0): d_loss = torch.empty(0, device=device) p_loss = torch.empty(0, device=device) v_loss = torch.empty(0, device=device) gen_r = torch.empty(0, device=device) expert_r = torch.empty(0, device=device) for expert_state_batch, expert_action_batch in data_loader: noise1 = torch.normal(0, args.noise_std, size=gen_state.shape, device=device) noise2 = torch.normal(0, args.noise_std, size=gen_action.shape, device=device) noise3 = torch.normal(0, args.noise_std, size=expert_state_batch.shape, device=device) noise4 = torch.normal(0, args.noise_std, size=expert_action_batch.shape, device=device) gen_r = discriminator(gen_state + noise1, gen_action + noise2) expert_r = discriminator( expert_state_batch.to(device) + noise3, expert_action_batch.to(device) + noise4) # gen_r = discriminator(gen_state, gen_action) # expert_r = discriminator(expert_state_batch.to(device), expert_action_batch.to(device)) optimizer_discriminator.zero_grad() d_loss = discriminator_criterion(gen_r, torch.zeros(gen_r.shape, device=device)) + \ discriminator_criterion(expert_r,torch.ones(expert_r.shape, device=device)) variance = 0.5 * torch.var(gen_r.to(device)) + 0.5 * torch.var( expert_r.to(device)) total_d_loss = d_loss - 10 * variance d_loss.backward() # total_d_loss.backward() optimizer_discriminator.step() if write_scalar: writer.add_scalar('d_loss', d_loss, ep) writer.add_scalar('total_d_loss', total_d_loss, ep) writer.add_scalar('variance', 10 * variance, ep) if ep % 1 == 0: # update PPO noise1 = torch.normal(0, args.noise_std, size=gen_state.shape, device=device) noise2 = torch.normal(0, args.noise_std, size=gen_action.shape, device=device) gen_r = discriminator(gen_state + noise1, gen_action + noise2) #if gen_r.mean().item() < 0.1: # d_stop = True #if d_stop and gen_r.mean() optimize_iter_num = int( math.ceil(onehot_state.shape[0] / args.ppo_mini_batch_size)) # gen_r = -(1 - gen_r + 1e-10).log() for ppo_ep in range(args.ppo_optim_epoch): for i in range(optimize_iter_num): num += 1 index = slice( i * args.ppo_mini_batch_size, min((i + 1) * args.ppo_mini_batch_size, onehot_state.shape[0])) onehot_state_batch, multihot_state_batch, continuous_state_batch, onehot_action_batch, multihot_action_batch, continuous_action_batch, \ old_log_prob_batch, mask_batch, next_onehot_state_batch, next_multihot_state_batch, next_continuous_state_batch, gen_r_batch = \ onehot_state[index], multihot_state[index], continuous_state[index], onehot_action[index], multihot_action[index], continuous_action[index], \ old_log_prob[index], mask[index], next_onehot_state[index], next_multihot_state[index], next_continuous_state[index], gen_r[ index] v_loss, p_loss = ppo_step( policy, value, optimizer_policy, optimizer_value, onehot_state_batch, multihot_state_batch, continuous_state_batch, onehot_action_batch, multihot_action_batch, continuous_action_batch, next_onehot_state_batch, next_multihot_state_batch, next_continuous_state_batch, gen_r_batch, old_log_prob_batch, mask_batch, args.ppo_clip_epsilon) if write_scalar: writer.add_scalar('p_loss', p_loss, ep) writer.add_scalar('v_loss', v_loss, ep) policy.eval() value.eval() discriminator.eval() noise1 = torch.normal(0, args.noise_std, size=gen_state.shape, device=device) noise2 = torch.normal(0, args.noise_std, size=gen_action.shape, device=device) gen_r = discriminator(gen_state + noise1, gen_action + noise2) expert_r = discriminator( expert_state_batch.to(device) + noise3, expert_action_batch.to(device) + noise4) gen_r_noise = gen_r.mean().item() expert_r_noise = expert_r.mean().item() gen_r = discriminator(gen_state, gen_action) expert_r = discriminator(expert_state_batch.to(device), expert_action_batch.to(device)) if write_scalar: writer.add_scalar('gen_r', gen_r.mean(), ep) writer.add_scalar('expert_r', expert_r.mean(), ep) writer.add_scalar('gen_r_noise', gen_r_noise, ep) writer.add_scalar('expert_r_noise', expert_r_noise, ep) print('#' * 5 + 'training episode:{}'.format(ep) + '#' * 5) print('gen_r_noise', gen_r_noise) print('expert_r_noise', expert_r_noise) print('gen_r:', gen_r.mean().item()) print('expert_r:', expert_r.mean().item()) print('d_loss', d_loss.item()) # save models if model_name is not None: torch.save( discriminator.state_dict(), './model_pkl/Discriminator_model_' + model_name + '.pkl') torch.save(policy.transition_net.state_dict(), './model_pkl/Transition_model_' + model_name + '.pkl') torch.save(policy.policy_net.state_dict(), './model_pkl/Policy_model_' + model_name + '.pkl') torch.save( policy.policy_net_action_std, './model_pkl/Policy_net_action_std_model_' + model_name + '.pkl') torch.save( policy.transition_net_state_std, './model_pkl/Transition_net_state_std_model_' + model_name + '.pkl') torch.save(value.state_dict(), './model_pkl/Value_model_' + model_name + '.pkl') memory.clear_memory()
generator = Generator(parameters) discriminator = Discriminator(parameters) print(f'Number of parameters in generator: {sum(p.numel() for p in generator.learnable_parameters())}') print(f'Number of parameters in discriminator: {sum(p.numel() for p in discriminator.learnable_parameters())}') # Create locations to store logs if not os.path.isdir('logs/'+ args.model_name): os.mkdir('logs/'+ args.model_name) if args.interm_sampling and not os.path.isdir('logs/'+ args.model_name + '/intermediate'): os.mkdir('logs/'+ args.model_name + '/intermediate') if args.use_trained: generator.load_state_dict(t.load('saved_models/trained_generator_' + args.model_name)) discriminator.load_state_dict(t.load('saved_models/trained_discriminator_' + args.model_name)) ce_result_valid = list(np.load('logs/{}/ce_result_valid.npy'.format(args.model_name))) ce_result_train = list(np.load('logs/{}/ce_result_train.npy'.format(args.model_name))) ce2_result_train = list(np.load('logs/{}/ce2_result_train.npy'.format(args.model_name))) ce2_result_valid = list(np.load('logs/{}/ce2_result_valid.npy'.format(args.model_name))) kld_result_valid = list(np.load('logs/{}/kld_result_valid.npy'.format(args.model_name))) kld_result_train = list(np.load('logs/{}/kld_result_train.npy'.format(args.model_name))) dg_result_train = list(np.load('logs/{}/dg_result_train.npy'.format(args.model_name))) dg_result_valid = list(np.load('logs/{}/dg_result_valid.npy'.format(args.model_name))) d_result_train = list(np.load('logs/{}/d_result_train.npy'.format(args.model_name))) d_result_valid = list(np.load('logs/{}/d_result_valid.npy'.format(args.model_name))) if args.use_cuda: generator = generator.cuda() discriminator = discriminator.cuda()
def main(data_dir): origin_img, uv_map_gt, uv_map_predicted = None, None, None if not os.path.exists(FLAGS['images']): os.mkdir(FLAGS['images']) # 1) Create Dataset of 300_WLP & Dataloader. wlp300 = PRNetDataset(root_dir=data_dir, transform=transforms.Compose([ ToTensor(), ToResize((416, 416)), ToNormalize(FLAGS["normalize_mean"], FLAGS["normalize_std"]) ])) wlp300_dataloader = DataLoader(dataset=wlp300, batch_size=FLAGS['batch_size'], shuffle=True, num_workers=1) # 2) Intermediate Processing. transform_img = transforms.Compose([ #transforms.ToTensor(), transforms.Normalize(FLAGS["normalize_mean"], FLAGS["normalize_std"]) ]) # 3) Create PRNet model. start_epoch, target_epoch = FLAGS['start_epoch'], FLAGS['target_epoch'] g_x = ResFCN256(resolution_input=416, resolution_output=416, channel=3, size=16) g_y = ResFCN256(resolution_input=416, resolution_output=416, channel=3, size=16) d_x = Discriminator() d_y = Discriminator() # Load the pre-trained weight if FLAGS['resume'] != "" and os.path.exists( os.path.join(FLAGS['pretrained'], FLAGS['resume'])): state = torch.load(os.path.join(FLAGS['pretrained'], FLAGS['resume'])) try: g_x.load_state_dict(state['g_x']) g_y.load_state_dict(state['g_y']) d_x.load_state_dict(state['d_x']) d_y.load_state_dict(state['d_y']) except Exception: g_x.load_state_dict(state['prnet']) start_epoch = state['start_epoch'] INFO("Load the pre-trained weight! Start from Epoch", start_epoch) else: start_epoch = 0 INFO( "Pre-trained weight cannot load successfully, train from scratch!") if torch.cuda.device_count() > 1: model = torch.nn.DataParallel(model) g_x.to(FLAGS["device"]) g_y.to(FLAGS["device"]) d_x.to(FLAGS["device"]) d_y.to(FLAGS["device"]) optimizer_g = torch.optim.Adam(itertools.chain(g_x.parameters(), g_y.parameters()), lr=FLAGS["lr"], betas=(0.5, 0.999)) optimizer_d = torch.optim.Adam(itertools.chain(d_x.parameters(), d_y.parameters()), lr=FLAGS["lr"]) scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer_g, gamma=0.99) stat_loss = SSIM(mask_path=FLAGS["mask_path"], gauss=FLAGS["gauss_kernel"]) loss = WeightMaskLoss(mask_path=FLAGS["mask_path"]) bce_loss = torch.nn.BCEWithLogitsLoss() bce_loss.to(FLAGS["device"]) l1_loss = nn.L1Loss().to(FLAGS["device"]) lambda_X = 10 lambda_Y = 10 #Loss function for adversarial for ep in range(start_epoch, target_epoch): bar = tqdm(wlp300_dataloader) loss_list_cycle_x = [] loss_list_cycle_y = [] loss_list_d_x = [] loss_list_d_y = [] real_label = torch.ones(FLAGS['batch_size']) fake_label = torch.zeros(FLAGS['batch_size']) for i, sample in enumerate(bar): real_y, real_x = sample['uv_map'].to( FLAGS['device']), sample['origin'].to(FLAGS['device']) # x -> y' -> x^ optimizer_g.zero_grad() fake_y = g_x(real_x) prediction = d_x(fake_y) loss_g_x = bce_loss(prediction, real_label) x_hat = g_y(fake_y) loss_cycle_x = l1_loss(x_hat, real_x) * lambda_X loss_x = loss_g_x + loss_cycle_x loss_x.backward(retain_graph=True) optimizer_g.step() loss_list_cycle_x.append(loss_x.item()) # y -> x' -> y^ optimizer_g.zero_grad() fake_x = g_y(real_y) prediction = d_y(fake_x) loss_g_y = bce_loss(prediction, real_label) y_hat = g_x(fake_x) loss_cycle_y = l1_loss(y_hat, real_y) * lambda_Y loss_y = loss_g_y + loss_cycle_y loss_y.backward(retain_graph=True) optimizer_g.step() loss_list_cycle_y.append(loss_y.item()) # d_x optimizer_d.zero_grad() pred_real = d_x(real_y) loss_d_x_real = bce_loss(pred_real, real_label) pred_fake = d_x(fake_y) loss_d_x_fake = bce_loss(pred_fake, fake_label) loss_d_x = (loss_d_x_real + loss_d_x_fake) * 0.5 loss_d_x.backward() loss_list_d_x.append(loss_d_x.item()) optimizer_d.step() if 'WGAN' in FLAGS['gan_type']: for p in d_x.parameters(): p.data.clamp_(-1, 1) # d_y optimizer_d.zero_grad() pred_real = d_y(real_x) loss_d_y_real = bce_loss(pred_real, real_label) pred_fake = d_y(fake_x) loss_d_y_fake = bce_loss(pred_fake, fake_label) loss_d_y = (loss_d_y_real + loss_d_y_fake) * 0.5 loss_d_y.backward() loss_list_d_y.append(loss_d_y.item()) optimizer_d.step() if 'WGAN' in FLAGS['gan_type']: for p in d_y.parameters(): p.data.clamp_(-1, 1) if ep % FLAGS["save_interval"] == 0: with torch.no_grad(): print( " {} [Loss_G_X] {} [Loss_G_Y] {} [Loss_D_X] {} [Loss_D_Y] {}" .format(ep, loss_list_g_x[-1], loss_list_g_y[-1], loss_list_d_x[-1], loss_list_d_y[-1])) origin = cv2.imread("./test_data/obama_origin.jpg") gt_uv_map = np.load("./test_data/test_obama.npy") origin, gt_uv_map = test_data_preprocess( origin), test_data_preprocess(gt_uv_map) origin, gt_uv_map = transform_img(origin), transform_img( gt_uv_map) origin_in = origin.unsqueeze_(0).cuda() pred_uv_map = g_x(origin_in).detach().cpu() save_image( [origin.cpu(), gt_uv_map.unsqueeze_(0).cpu(), pred_uv_map], os.path.join(FLAGS['images'], str(ep) + '.png'), nrow=1, normalize=True) # Save model print("Save model") state = { 'g_x': g_x.state_dict(), 'g_y': g_y.state_dict(), 'd_x': d_x.state_dict(), 'd_y': d_y.state_dict(), 'start_epoch': ep, } torch.save(state, os.path.join(FLAGS['images'], '{}.pth'.format(ep))) scheduler.step()
class Trainer: def __init__(self, config, data_loader): self.device = torch.device( "cuda:0" if torch.cuda.is_available() else "cpu") self.in_channels = config.in_channels self.out_channels = config.out_channels self.nf = config.nf self.storing_channels = config.storing_channels self.lr = config.lr self.b1 = config.b1 self.b2 = config.b2 self.weight_decay = config.weight_decay self.decay_epoch = config.decay_epoch self.content_loss_factor = config.content_loss_factor self.perceptual_loss_factor = config.perceptual_loss_factor self.generator_loss_factor = config.generator_loss_factor self.discriminator_loss_factor = config.discriminator_loss_factor self.penalty_loss_factor = config.penalty_loss_factor self.eta = config.eta self.checkpoint_dir = config.checkpoint_dir self.sample_dir = config.sample_dir self.epoch = config.epoch self.num_epoch = config.num_epoch self.image_size = config.image_size self.data_loader = data_loader self.content_losses = AverageMeter() self.generator_losses = AverageMeter() self.perceptual_losses = AverageMeter() self.discriminator_losses = AverageMeter() self.ae_losses = AverageMeter() self.visdom = Visdom() self.build_model() def train(self): optimizer_ae = Adam(chain(self.Encoder.parameters(), self.Decoder.parameters()), self.lr, betas=(self.b1, self.b2), weight_decay=self.weight_decay) optimizer_discriminator = Adam(self.Disciminator.parameters(), self.lr, betas=(self.b1, self.b2), weight_decay=self.weight_decay) lr_scheduler = torch.optim.lr_scheduler.LambdaLR( optimizer_ae, LambdaLR(self.num_epoch, self.epoch, self.decay_epoch).step) total_step = len(self.data_loader) perceptual_criterion = PerceptualLoss().to(self.device) content_criterion = nn.L1Loss().to(self.device) adversarial_criterion = nn.BCELoss().to(self.device) self.Encoder.train() self.Decoder.train() content_losses = AverageMeter() generator_losses = AverageMeter() perceptual_losses = AverageMeter() discriminator_losses = AverageMeter() ae_losses = AverageMeter() lr_window = create_vis_plot('Epoch', 'Learning rate', 'Learning rate') loss_window = create_vis_plot('Epoch', 'Loss', 'Total Loss') generator_loss_window = create_vis_plot('Epoch', 'Loss', 'Generator Loss') discriminator_loss_window = create_vis_plot('Epoch', 'Loss', 'Discriminator Loss') content_loss_window = create_vis_plot('Epoch', 'Loss', 'Content Loss') perceptual_loss_window = create_vis_plot('Epoch', 'Loss', 'Perceptual Loss') if not os.path.exists(self.sample_dir): os.makedirs(self.sample_dir) if not os.path.exists(self.checkpoint_dir): os.makedirs(self.checkpoint_dir) for epoch in range(self.epoch, self.num_epoch): content_losses.reset() perceptual_losses.reset() generator_losses.reset() ae_losses.reset() discriminator_losses.reset() for step, images in enumerate(self.data_loader): images = images.to(self.device) real_labels = torch.ones((images.size(0), 1)).to(self.device) fake_labels = torch.zeros((images.size(0), 1)).to(self.device) encoded_image = self.Encoder(images) binary_decoded_image = paq.compress( encoded_image.cpu().detach().numpy().tobytes()) # encoded_image = paq.decompress(binary_decoded_image) # # encoded_image = torch.from_numpy(np.frombuffer(encoded_image, dtype=np.float32) # .reshape(-1, self.storing_channels, self.image_size // 8, # self.image_size // 8)).to(self.device) decoded_image = self.Decoder(encoded_image) content_loss = content_criterion(images, decoded_image) perceptual_loss = perceptual_criterion(images, decoded_image) generator_loss = adversarial_criterion( self.Disciminator(decoded_image), real_labels) # generator_loss = -self.Disciminator(decoded_image).mean() ae_loss = content_loss * self.content_loss_factor + perceptual_loss * self.perceptual_loss_factor + \ generator_loss * self.generator_loss_factor content_losses.update(content_loss.item()) perceptual_losses.update(perceptual_loss.item()) generator_losses.update(generator_loss.item()) ae_losses.update(ae_loss.item()) optimizer_ae.zero_grad() ae_loss.backward(retain_graph=True) optimizer_ae.step() interpolated_image = self.eta * images + ( 1 - self.eta) * decoded_image gravity_penalty = self.Disciminator(interpolated_image).mean() real_loss = adversarial_criterion(self.Disciminator(images), real_labels) fake_loss = adversarial_criterion( self.Disciminator(decoded_image), fake_labels) discriminator_loss = (real_loss + fake_loss) * self.discriminator_loss_factor / 2 +\ gravity_penalty * self.penalty_loss_factor # discriminator_loss = self.Disciminator(decoded_image).mean() - self.Disciminator(images).mean() + \ # gravity_penalty * self.penalty_loss_factor optimizer_discriminator.zero_grad() discriminator_loss.backward(retain_graph=True) optimizer_discriminator.step() discriminator_losses.update(discriminator_loss.item()) if step % 100 == 0: print( f"[Epoch {epoch}/{self.num_epoch}] [Batch {step}/{total_step}] [Learning rate {get_lr(optimizer_ae)}] " f"[Content {content_loss:.4f}] [Perceptual {perceptual_loss:.4f}] [Gan {generator_loss:.4f}]" f"[Discriminator {discriminator_loss:.4f}]") save_image( torch.cat([images, decoded_image], dim=2), os.path.join(self.sample_dir, f"Sample-epoch-{epoch}-step-{step}.png")) update_vis_plot(epoch, ae_losses.avg, loss_window, 'append') update_vis_plot(epoch, generator_losses.avg, generator_loss_window, 'append') update_vis_plot(epoch, discriminator_losses.avg, discriminator_loss_window, 'append') update_vis_plot(epoch, content_losses.avg, content_loss_window, 'append') update_vis_plot(epoch, perceptual_losses.avg, perceptual_loss_window, 'append') update_vis_plot(epoch, get_lr(optimizer_ae), lr_window, 'append') lr_scheduler.step() torch.save( self.Encoder.state_dict(), os.path.join(self.checkpoint_dir, f"Encoder-{epoch}.pth")) torch.save( self.Decoder.state_dict(), os.path.join(self.checkpoint_dir, f"Decoder-{epoch}.pth")) torch.save( self.Disciminator.state_dict(), os.path.join(self.checkpoint_dir, f"Discriminator-{epoch}.pth")) def build_model(self): self.Encoder = Encoder(self.in_channels, self.storing_channels, self.nf).to(self.device) self.Decoder = Decoder(self.storing_channels, self.in_channels, self.nf).to(self.device) self.Disciminator = Discriminator().to(self.device) self.load_model() def load_model(self): print(f"[*] Load Model in {self.checkpoint_dir}") if not os.path.exists(self.checkpoint_dir): os.makedirs(self.checkpoint_dir) encoder_parameter_names = glob( os.path.join(self.checkpoint_dir, f"Encoder-{self.epoch - 1}.pth")) decoder_parameter_names = glob( os.path.join(self.checkpoint_dir, f"Decoder-{self.epoch - 1}.pth")) discriminator_parameters_names = glob( os.path.join(self.checkpoint_dir, f"Discriminator-{self.epoch - 1}.pth")) if not encoder_parameter_names or not decoder_parameter_names or not discriminator_parameters_names: print(f"[!] There is no parameter in {self.checkpoint_dir}") return self.Encoder.load_state_dict(torch.load(encoder_parameter_names[0])) self.Decoder.load_state_dict(torch.load(decoder_parameter_names[0])) self.Disciminator.load_state_dict( torch.load(discriminator_parameters_names[0]))
def main(): # define actor/critic/discriminator net and optimizer policy = Policy(discrete_action_sections, discrete_state_sections) value = Value() discriminator = Discriminator() optimizer_policy = torch.optim.Adam(policy.parameters(), lr=args.policy_lr) optimizer_value = torch.optim.Adam(value.parameters(), lr=args.value_lr) optimizer_discriminator = torch.optim.Adam(discriminator.parameters(), lr=args.discrim_lr) discriminator_criterion = nn.BCELoss() writer = SummaryWriter() # load expert data dataset = ExpertDataSet(args.expert_activities_data_path, args.expert_cost_data_path) data_loader = data.DataLoader(dataset=dataset, batch_size=args.expert_batch_size, shuffle=False, num_workers=1) # load models discriminator.load_state_dict( torch.load('./model_pkl/Discriminator_model_2.pkl')) policy.transition_net.load_state_dict( torch.load('./model_pkl/Transition_model_2.pkl')) policy.policy_net.load_state_dict( torch.load('./model_pkl/Policy_model_2.pkl')) value.load_state_dict(torch.load('./model_pkl/Value_model_2.pkl')) print('############# start training ##############') # update discriminator num = 0 for ep in tqdm(range(args.training_epochs)): # collect data from environment for ppo update start_time = time.time() memory = policy.collect_samples(args.ppo_buffer_size, size=10000) # print('sample_data_time:{}'.format(time.time()-start_time)) batch = memory.sample() continuous_state = torch.stack( batch.continuous_state).squeeze(1).detach() discrete_action = torch.stack( batch.discrete_action).squeeze(1).detach() continuous_action = torch.stack( batch.continuous_action).squeeze(1).detach() next_discrete_state = torch.stack( batch.next_discrete_state).squeeze(1).detach() next_continuous_state = torch.stack( batch.next_continuous_state).squeeze(1).detach() old_log_prob = torch.stack(batch.old_log_prob).detach() mask = torch.stack(batch.mask).squeeze(1).detach() discrete_state = torch.stack(batch.discrete_state).squeeze(1).detach() d_loss = torch.empty(0, device=device) p_loss = torch.empty(0, device=device) v_loss = torch.empty(0, device=device) gen_r = torch.empty(0, device=device) expert_r = torch.empty(0, device=device) for _ in range(1): for expert_state_batch, expert_action_batch in data_loader: gen_state = torch.cat((discrete_state, continuous_state), dim=-1) gen_action = torch.cat((discrete_action, continuous_action), dim=-1) gen_r = discriminator(gen_state, gen_action) expert_r = discriminator(expert_state_batch, expert_action_batch) optimizer_discriminator.zero_grad() d_loss = discriminator_criterion(gen_r, torch.zeros(gen_r.shape, device=device)) + \ discriminator_criterion(expert_r, torch.ones(expert_r.shape, device=device)) total_d_loss = d_loss - 10 * torch.var(gen_r.to(device)) d_loss.backward() # total_d_loss.backward() optimizer_discriminator.step() writer.add_scalar('d_loss', d_loss, ep) # writer.add_scalar('total_d_loss', total_d_loss, ep) writer.add_scalar('expert_r', expert_r.mean(), ep) # update PPO gen_r = discriminator( torch.cat((discrete_state, continuous_state), dim=-1), torch.cat((discrete_action, continuous_action), dim=-1)) optimize_iter_num = int( math.ceil(discrete_state.shape[0] / args.ppo_mini_batch_size)) for ppo_ep in range(args.ppo_optim_epoch): for i in range(optimize_iter_num): num += 1 index = slice( i * args.ppo_mini_batch_size, min((i + 1) * args.ppo_mini_batch_size, discrete_state.shape[0])) discrete_state_batch, continuous_state_batch, discrete_action_batch, continuous_action_batch, \ old_log_prob_batch, mask_batch, next_discrete_state_batch, next_continuous_state_batch, gen_r_batch = \ discrete_state[index], continuous_state[index], discrete_action[index], continuous_action[index], \ old_log_prob[index], mask[index], next_discrete_state[index], next_continuous_state[index], gen_r[ index] v_loss, p_loss = ppo_step( policy, value, optimizer_policy, optimizer_value, discrete_state_batch, continuous_state_batch, discrete_action_batch, continuous_action_batch, next_discrete_state_batch, next_continuous_state_batch, gen_r_batch, old_log_prob_batch, mask_batch, args.ppo_clip_epsilon) writer.add_scalar('p_loss', p_loss, num) writer.add_scalar('v_loss', v_loss, num) writer.add_scalar('gen_r', gen_r.mean(), num) print('#' * 5 + 'training episode:{}'.format(ep) + '#' * 5) print('d_loss', d_loss.item()) # print('p_loss', p_loss.item()) # print('v_loss', v_loss.item()) print('gen_r:', gen_r.mean().item()) print('expert_r:', expert_r.mean().item()) memory.clear_memory() # save models torch.save(discriminator.state_dict(), './model_pkl/Discriminator_model_3.pkl') torch.save(policy.transition_net.state_dict(), './model_pkl/Transition_model_3.pkl') torch.save(policy.policy_net.state_dict(), './model_pkl/Policy_model_3.pkl') torch.save(value.state_dict(), './model_pkl/Value_model_3.pkl')
batch_size = 40 epoch_total = 1000 n_dis = 1 is_cuda = True display_step = 10 save_step = 100 # net_pretrain = '/home/elijha/Documents/PycharmProjects/ReIDGAN/workdir/save/save-3400' net_pretrain = True # build graph if net_pretrain: feature_extractor = resnet50( pretrained_path="/home/nhli/PycharmProj/ReIDGAN_/params/save-fea-2000" ) # pretrained dis = Discriminator() dis.load_state_dict( torch.load("/home/nhli/PycharmProj/ReIDGAN_/params/save-dis-2000")) else: feature_extractor = resnet50(pretrained_path=None) dis = Discriminator() if is_cuda: feature_extractor.cuda() dis.cuda() # input pipeline data_iter = DataProvider(batch_size, is_cuda=is_cuda) # summary writer writer = SummaryWriter("/home/nhli/PycharmProj/ReIDGAN_/workdir/log/", 'comment test')
class RefSRSolver(BaseSolver): def __init__(self, cfg): super(RefSRSolver, self).__init__(cfg) self.srntt = SRNTT(cfg['model']['n_resblocks'], cfg['schedule']['use_weights'], cfg['schedule']['concat']).cuda() # self.discriminator = None self.discriminator = Discriminator(cfg['data']['input_size']).cuda() # self.vgg = None self.vgg = VGG19(cfg['model']['final_layer'], cfg['model']['prev_layer'], True).cuda() params = list(self.srntt.texture_transfer.parameters()) + list(self.srntt.texture_fusion_medium.parameters()) +\ list(self.srntt.texture_fusion_large.parameters()) + list(self.srntt.srntt_out.parameters()) self.init_epoch = self.cfg['schedule']['init_epoch'] self.num_epochs = self.cfg['schedule']['num_epochs'] self.optimizer_init = torch.optim.Adam(params, lr=cfg['schedule']['lr']) self.optimizer = torch.optim.lr_scheduler.MultiStepLR( torch.optim.Adam(params, lr=cfg['schedule']['lr']), [self.num_epochs // 2], 0.1) self.optimizer_d = torch.optim.lr_scheduler.MultiStepLR( torch.optim.Adam(self.discriminator.parameters(), lr=cfg['schedule']['lr']), [self.num_epochs // 2], 0.1) self.reconst_loss = nn.L1Loss() self.bp_loss = BackProjectionLoss() self.texture_loss = TextureLoss(self.cfg['schedule']['use_weights'], 80) self.adv_loss = AdvLoss(self.cfg['schedule']['is_WGAN_GP']) self.loss_weights = self.cfg['schedule']['loss_weights'] def train(self): if self.epoch <= self.init_epoch: with tqdm(total=len(self.train_loader), miniters=1, desc='Initial Training Epoch: [{}/{}]'.format( self.epoch, self.max_epochs)) as t: for data in self.train_loader: lr, hr = data['lr'].cuda(), data['hr'].cuda() maps, weight = data['map'].cuda(), data['weight'].cuda() self.srntt.train() self.optimizer_init.zero_grad() sr, srntt_out = self.srntt(lr, weight, maps) loss_reconst = self.reconst_loss(sr, hr) loss_bp = self.bp_loss(lr, srntt_out) loss = self.loss_weights[ 4] * loss_reconst + self.loss_weights[3] * loss_bp t.set_postfix_str("Batch loss {:.4f}".format(loss.item())) t.update() loss.backward() self.optimizer_init.step() elif self.epoch <= self.num_epochs: with tqdm(total=len(self.train_loader), miniters=1, desc='Complete Training Epoch: [{}/{}]'.format( self.epoch, self.max_epochs)) as t: for data in self.train_loader: lr, hr = data['lr'].cuda(), data['hr'].cuda() maps, weight = data['map'].cuda(), data['weight'].cuda() self.srntt.train() self.optimizer_init.zero_grad() self.optimizer.optimizer.zero_grad() self.optimizer_d.optimizer.zero_grad() sr, srntt_out = self.srntt(lr, weight, maps) sr_prevlayer, sr_lastlayer = self.vgg(srntt_out) hr_prevlayer, hr_lastlayer = self.vgg(hr) _, d_real_logits = self.discriminator(hr) _, d_fake_logits = self.discriminator(srntt_out) loss_reconst = self.reconst_loss(sr, hr) loss_bp = self.bp_loss(lr, srntt_out) loss_texture = self.texture_loss(sr_prevlayer, maps, weight) loss_d, loss_g = self.adv_loss(srntt_out, hr, d_fake_logits, d_real_logits, self.discriminator) loss_percep = torch.pow(sr_lastlayer - hr_lastlayer, 2).mean() if self.cfg['schedule']['use_lower_layers_in_per_loss']: for l_sr, l_hr in zip(sr_prevlayer, hr_prevlayer): loss_percep += torch.pow(l_sr - l_hr, 2).mean() loss_percep = loss_percep / (len(sr_prevlayer) + 1) weighted_loss = torch.Tensor(self.loss_weights).cuda() * \ torch.Tensor([loss_percep, loss_texture, loss_g, loss_bp, loss_reconst]) total_loss = weighted_loss.sum() t.set_postfix_str("Batch loss {:.4f}".format( total_loss.item())) t.update() loss_d.backward() total_loss.backward() self.optimizer.step(self.epoch) self.optimizer_d.step(self.epoch) else: pass def eval(self): with tqdm(total=len(self.val_loader), miniters=1, desc='Val Epoch: [{}/{}]'.format(self.epoch, self.max_epochs)) as t: psnr_list, ssim_list, loss_list = [], [], [] for lr, hr in self.val_loader: lr, hr = lr.cuda(), hr.cuda() self.srntt.eval() with torch.no_grad(): sr, _ = self.srntt(lr, None, None) loss = self.reconst_loss(sr, hr) batch_psnr, batch_ssim = [], [] for c in range(sr.shape[0]): predict_sr = (sr[c, ...].cpu().numpy().transpose( (1, 2, 0)) + 1) * 127.5 ground_truth = (hr[c, ...].cpu().numpy().transpose( (1, 2, 0)) + 1) * 127.5 psnr = utils.calculate_psnr(predict_sr, ground_truth, 255) ssim = utils.calculate_ssim(predict_sr, ground_truth, 255) batch_psnr.append(psnr) batch_ssim.append(ssim) avg_psnr = np.array(batch_psnr).mean() avg_ssim = np.array(batch_ssim).mean() psnr_list.extend(batch_psnr) ssim_list.extend(batch_ssim) t.set_postfix_str( 'Batch loss: {:.4f}, PSNR: {:.4f}, SSIM: {:.4f}'.format( loss.item(), avg_psnr, avg_ssim)) t.update() self.records['Epoch'].append(self.epoch) self.records['PSNR'].append(np.array(psnr_list).mean()) self.records['SSIM'].append(np.array(ssim_list).mean()) self.logger.log('Val Epoch {}: PSNR={}, SSIM={}'.format( self.epoch, self.records['PSNR'][-1], self.records['SSIM'][-1])) def save_checkpoint(self): super(RefSRSolver, self).save_checkpoint() self.ckp['srntt'] = self.srntt.state_dict() self.ckp['optimizer'] = self.optimizer.state_dict() self.ckp['optimizer_d'] = self.optimizer_d.state_dict() self.ckp['optimizer_init'] = self.optimizer_init.state_dict() if self.discriminator is not None: self.ckp['discriminator'] = self.discriminator.state_dict() if self.vgg is not None: self.ckp['vgg'] = self.vgg.state_dict() torch.save(self.ckp, os.path.join(self.checkpoint_dir, 'latest.pth')) if self.records['PSNR'][-1] == np.array(self.records['PSNR']).max(): shutil.copy(os.path.join(self.checkpoint_dir, 'latest.pth'), os.path.join(self.checkpoint_dir, 'best.pth')) def load_checkpoint(self, model_path): super(RefSRSolver, self).load_checkpoint(model_path) ckpt = torch.load(model_path) self.srntt.load_state_dict(ckpt['srntt']) self.optimizer.load_state_dict(ckpt['optimizer']) self.optimizer_d.load_state_dict(ckpt['optimizer_d']) self.optimizer_init.load_state_dict(ckpt['optimizer_init']) if 'vgg' in ckpt.keys() and self.vgg is not None: self.vgg.load_stat_dict(ckpt['srntt']) if 'discriminator' in ckpt.keys() and self.discriminator is not None: self.discriminator.load_state_dict(ckpt['discriminator'])