Example #1
0
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()
Example #2
0
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))