def train(): device = torch.device('cuda') if torch.cuda.is_available() else 'cpu' transforms = tv.transforms.Compose([ tv.transforms.Resize(IMG_SIZE), tv.transforms.CenterCrop(IMG_SIZE), tv.transforms.ToTensor(), tv.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) vis = Visualizer(env) # drop_last: retain data that cannot suffice a batch dataset = tv.datasets.ImageFolder(DATA_PATH, transforms) dataloader = data.DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4, drop_last=True) netG, netD = G(DIM_NOISE, DIM_G), D(DIM_D) netG.to(device) netD.to(device) # Optimizers and Loss functions optimizer_G = torch.optim.Adam(netG.parameters(), lr=LR_G, betas=(0.5, 0.999)) optimizer_D = torch.optim.Adam(netG.parameters(), lr=LR_D, betas=(0.5, 0.999)) criterion = nn.BCELoss().to(device) noises = torch.randn(BATCH_SIZE, DIM_NOISE, 1, 1).to(device) errord_meter = AverageValueMeter() errorg_meter = AverageValueMeter() # Real imgs have 0 loss; fake imgs have 1 true_labels = torch.ones(BATCH_SIZE).to(device) fake_labels = torch.zeros(BATCH_SIZE).to(device) max_epoch_G, max_epoch_D = 0, 0 # Load pretrained network with greatest number of training epochs pretrained_root_g = MODEL_SAVE_PATH + 'G/' if PRETRAINED and os.path.exists(pretrained_root_g): file_list = [ file for file in os.listdir(pretrained_root_g) if file.endswith('.pth') ] if file_list != []: index_list = [ int(file.split('.pth')[0].split('_')[2]) for file in file_list ] max_epoch_G = max(index_list) model_name = 'model_g_%s.pth' % max_epoch_G print('Using mode:', model_name) netG.load_state_dict(torch.load(pretrained_root_g + model_name)) netG.to(device) else: print('Generator train from Step 0') pretrained_root_d = MODEL_SAVE_PATH + 'D/' if PRETRAINED and os.path.exists(pretrained_root_d): file_list = [ file for file in os.listdir(pretrained_root_d) if file.endswith('.pth') ] if file_list != []: index_list = [ int(file.split('.pth')[0].split('_')[2]) for file in file_list ] max_epoch_D = max(index_list) model_name = 'model_d_%s.pth' % max_epoch_D print('Using mode:', model_name) netD.load_state_dict(torch.load(pretrained_root_d + model_name)) netD.to(device) else: print('Discriminator train from Epoch 0') for epoch in range(EPOCHS): time_start = time.time() for step, (img, _) in enumerate(dataloader): # Skip former steps if using pretrained models real_img = img.to(device) if step <= max_epoch_G and step <= max_epoch_D: continue # Train generator if step % GENERATE_EVERY == 0 and step > max_epoch_G: print('G - Epoch:', epoch, '| Step:', step) optimizer_G.zero_grad() noises.data.copy_( torch.randn(BATCH_SIZE, DIM_NOISE, 1, 1) ) # TODO: Why not noises=(torch.randn(BATCH_SIZE, DIM_NOISE, 1, 1)) fake_img = netG(noises) output_g = netD(fake_img) loss_g = criterion(output_g, true_labels) loss_g.backward() optimizer_G.step() errorg_meter.add(loss_g.item()) if step % DISCRIMINATE_EVERY == 0 and step > max_epoch_D: # Identify real images print('D - Epoch:', epoch, '| Step:', step) output_d = netD(real_img) loss_real = criterion(output_d, true_labels) loss_real.backward() # Identify fake images optimizer_D.zero_grad() noises.data.copy_(torch.randn(BATCH_SIZE, DIM_NOISE, 1, 1)) fake_img = netG(noises) output_d = netD(fake_img) loss_fake = criterion(output_d, fake_labels) loss_fake.backward() optimizer_D.step() loss_d = loss_real + loss_fake errord_meter.add(loss_d.item()) #fake_img = fake_img.detach() if (step + 1) % PLOT_EVERY: fix_fake_imgs = netG(noises) vis.images(fix_fake_imgs.detach().cpu().numpy()[:64] * 0.5 + 0.5, win='fixfake') vis.images(real_img.data.cpu().numpy()[:64] * 0.5 + 0.5, win='real') vis.plot('errord', errord_meter.value()[0]) vis.plot('errorg', errorg_meter.value()[0]) time_end = time.time() print('Total time for epoch ', epoch, ' is ', (time_end - time_start)) if epoch and epoch % SAVE_EVERY == 0: torch.save(netG.state_dict(), MODEL_SAVE_PATH + 'G/model_g_%s.pth' % step) torch.save(netD.state_dict(), MODEL_SAVE_PATH + 'D/model_d_%s.pth' % step) errord_meter.reset() errorg_meter.reset()
def train(**kwargs): ''' 训练函数 :param kwargs: fire传进来的训练参数 :return: ''' opt.parse(kwargs) for k_,v_ in kwargs.items(): setattr(opt,k_,v_) if opt.vis: vis = Visualizer(opt.env) #step1:数据预处理 transforms = tv.transforms.Compose([ tv.transforms.Resize(opt.image_size), tv.transforms.CenterCrop(opt.image_size), tv.transforms.ToTensor(), tv.transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)) ]) dataset = tv.datasets.ImageFolder(opt.data_path,transform=transforms) dataloader = t.utils.data.DataLoader(dataset, batch_size=opt.batch_size, shuffle=True, num_workers=opt.num_workers, drop_last=True) #step2: 定义网络 netg,netd = NetG(opt),NetD(opt) map_location = lambda storage,loc:storage if opt.netd_path: netd.load_state_dict(t.load(opt.netd_path, map_location=map_location)) if opt.netg_path: netg.load_state_dict(t.load(opt.netg_path, map_location=map_location)) #定义优化器和损失函数 optimizer_g = t.optim.Adam(netg.parameters(), opt.lrG, betas=(0.5, 0.999)) optimizer_d = t.optim.Adam(netd.parameters(), opt.lrD, betas=(0.5, 0.999)) criterion = t.nn.BCELoss() #真图片label为1,加图片label为0 #noise为网络的输入 true_labels = t.ones(opt.batch_size) fake_labels = t.zeros(opt.batch_size) fix_noises = t.randn(opt.batch_size,opt.nz,1,1) noises = t.randn(opt.batch_size,opt.nz,1,1) errord_meter = AverageValueMeter() errorg_meter = AverageValueMeter() if opt.gpu: device = t.device("cuda:0" if t.cuda.is_available() else "cpu") netd.to(device) netg.to(device) criterion.to(device) true_labels,fake_labels = true_labels.to(device),fake_labels.to(device) fix_noises,noises = fix_noises.to(device),noises.to(device) epochs = range(140) for epoch in iter(epochs): for ii,(img,_) in tqdm.tqdm(enumerate(dataloader),total=len(dataloader)): if opt.gpu: real_img = img.to(device) if ii%opt.d_every == 0: #每个batch训练一次鉴别器 optimizer_d.zero_grad() output = netd(real_img) #判断真图片(使其尽可能大) error_d_real = criterion(output,true_labels) error_d_real.backward() ##尽可能把假图片判断为错误 noises.data.copy_(t.randn(opt.batch_size,opt.nz,1,1)) fake_img = netg(noises).detach() #根据噪声生成假图 output = netd(fake_img) error_d_fake = criterion(output,fake_labels) error_d_fake.backward() optimizer_d.step() error_d = error_d_fake + error_d_real errord_meter.add(error_d.item()) if ii%opt.g_every == 0: #每5个batch更新一次生成器 #训练生成器 optimizer_g.zero_grad() noises.data.copy_(t.randn(opt.batch_size, opt.nz, 1, 1)) fake_img = netg(noises) output = netd(fake_img) error_g = criterion(output,true_labels) error_g.backward() optimizer_g.step() errord_meter.add(error_g.item()) if opt.vis and ii%opt.plot_time == opt.plot_time - 1: ##可视化 fix_fake_img = netg(fix_noises) #使用噪声生成图片 vis.images(fix_fake_img.data.cpu().numpy()[:64]*0.5+0.5,win = 'fixfake') # vis.images(real_img.data.cpu().numpy()[:64]*0.5+0.5,win = 'real') vis.plot('errord', errord_meter.value()[0]) vis.plot('errorg', errorg_meter.value()[0]) if epoch%opt.decay_every == opt.decay_every-1: #保存模型,图片 tv.utils.save_image(fix_fake_img.data[:64],'%s/new%s.png'%(opt.save_path,epoch), normalize=True,range=(-1,1)) t.save(netd.state_dict(), 'checkpoints/new_netd_%s.pth' % epoch) t.save(netg.state_dict(), 'checkpoints/new_netg_%s.pth' % epoch) errord_meter.reset() errorg_meter.reset() optimizer_g = t.optim.Adam(netg.parameters(), opt.lrG, betas=(0.5, 0.999)) optimizer_d = t.optim.Adam(netd.parameters(), opt.lrD, betas=(0.5, 0.999))