示例#1
0
文件: test.py 项目: takuhirok/CP-GAN
def main():
    parser = argparse.ArgumentParser()
    # Seed option
    parser.add_argument('--seed', default=0, type=int)
    # GPU option
    parser.add_argument('--gpu_id', type=int, default=0)
    # Dataset option
    parser.add_argument('--dataset', type=str, default='cifar10to5')
    # Genrator option
    parser.add_argument('--g_path', type=str, required=True)
    # Output options
    parser.add_argument('--out', type=str, default='samples')
    parser.add_argument('--num_samples', type=int, default=10)
    parser.add_argument('--eval_batch_size', type=int, default=128)
    args = parser.parse_args()

    # Set up seed
    torch.manual_seed(args.seed)
    torch.cuda.manual_seed(args.seed)

    # Set up GPU
    if torch.cuda.is_available() and args.gpu_id >= 0:
        device = torch.device('cuda:%d' % args.gpu_id)
    else:
        device = torch.device('cpu')

    # Set up dataset
    if args.dataset == 'cifar10':
        vis_label_list = [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
    elif args.dataset == 'cifar10to5':
        vis_label_list = [[0], [0, 1], [1], [1, 2], [2], [2, 3], [3], [3, 4],
                          [4], [4, 0]]
    elif args.dataset == 'cifar7to3':
        vis_label_list = [[0], [0, 1], [1], [1, 2], [2], [2, 0], [0, 1, 2]]

    # Set up generator
    g_root = os.path.dirname(args.g_path)
    g_params = util.load_params(os.path.join(g_root, 'netG_params.pkl'))
    g_iteration = int(
        os.path.splitext(os.path.basename(args.g_path))[0].split('_')[-1])
    netG = resnet.Generator(**g_params)
    netG.to(device)
    netG.load_state_dict(
        torch.load(args.g_path, map_location=lambda storage, loc: storage))
    netG.eval()

    # Set up output
    if not os.path.exists(args.out):
        os.makedirs(args.out)

    # Set up visualizer
    visualizer = Visualizer(netG, vis_label_list, device, args.out,
                            args.num_samples, args.eval_batch_size)

    # Visualize
    visualizer.visualize(g_iteration)
示例#2
0
def main():
    # For fast training
    cudnn.benchmark = True

    parser = argparse.ArgumentParser()
    # GPU option
    parser.add_argument('--gpu_id', type=int, default=0)
    # Dataset options
    parser.add_argument('--dataset', type=str, default='cifar10to5')
    parser.add_argument('--dataroot', type=str, default='data')
    parser.add_argument('--data_seed', type=int, default=12345)
    parser.add_argument('--num_workers', type=int, default=4)
    # Model options
    parser.add_argument('--latent_dim', type=int, default=128)
    parser.add_argument('--image_size', type=int, default=32)
    parser.add_argument('--g_channels', type=int, default=128)
    parser.add_argument('--g_spectral_norm', type=int, default=0)
    parser.add_argument('--d_channels', type=int, default=128)
    parser.add_argument('--d_dropout', type=int, default=1)
    parser.add_argument('--d_spectral_norm', type=int, default=0)
    parser.add_argument('--d_pooling', type=str, default='mean')
    # Training options
    parser.add_argument('--trainer', type=str, default='cpgan')
    parser.add_argument('--gan_loss', type=str, default='wgan')
    parser.add_argument('--batch_size', type=int, default=64)
    parser.add_argument('--g_bs_multiple', type=int, default=2)
    parser.add_argument('--g_lr', type=float, default=2e-4)
    parser.add_argument('--d_lr', type=float, default=2e-4)
    parser.add_argument('--beta1', type=float, default=0.)
    parser.add_argument('--beta2', type=float, default=0.9)
    parser.add_argument('--num_critic', type=int, default=5)
    parser.add_argument('--lambda_gp', type=float, default=10.)
    parser.add_argument('--lambda_ct', type=float, default=0.)
    parser.add_argument('--lambda_cls_g', type=float, default=0.4)
    parser.add_argument('--lambda_cls_d', type=float, default=1.)
    parser.add_argument('--factor_m', type=float, default=0.)
    parser.add_argument('--num_iterations', type=int, default=100000)
    parser.add_argument('--num_iterations_decay', type=int, default=100000)
    # Output options
    parser.add_argument('--out', type=str, default='outputs')
    parser.add_argument('--display_interval', type=int, default=100)
    parser.add_argument('--snapshot_interval', type=int, default=5000)
    parser.add_argument('--visualize_interval', type=int, default=5000)
    parser.add_argument('--num_samples', type=int, default=10)
    parser.add_argument('--eval_batch_size', type=int, default=128)
    args = parser.parse_args()
    args.g_spectral_norm = bool(args.g_spectral_norm)
    args.d_dropout = bool(args.d_dropout)
    args.d_spectral_norm = bool(args.d_spectral_norm)

    # Set up GPU
    if torch.cuda.is_available() and args.gpu_id >= 0:
        device = torch.device('cuda:%d' % args.gpu_id)
    else:
        device = torch.device('cpu')

    # Set up dataset
    if args.dataset == 'cifar10':
        args.num_classes = 10
        Dataset = torchvision.datasets.CIFAR10
        args.vis_label_list = [[0], [1], [2], [3], [4], [5], [6], [7], [8],
                               [9]]
    elif args.dataset == 'cifar10to5':
        args.num_classes = 5
        Dataset = functools.partial(datasets.CIFAR10to5, seed=args.data_seed)
        args.vis_label_list = [[0], [0, 1], [1], [1, 2], [2], [2, 3], [3],
                               [3, 4], [4], [4, 0]]
    elif args.dataset == 'cifar7to3':
        args.num_classes = 3
        Dataset = functools.partial(datasets.CIFAR7to3, seed=args.data_seed)
        args.vis_label_list = [[0], [0, 1], [1], [1, 2], [2], [2, 0],
                               [0, 1, 2]]

    def normalize(x):
        x = 2 * ((x * 255. / 256.) - .5)
        x += torch.zeros_like(x).uniform_(0, 1. / 128)
        return x

    dataset = Dataset(root=args.dataroot,
                      train=True,
                      download=True,
                      transform=transforms.Compose([
                          transforms.ToTensor(),
                          transforms.Lambda(normalize)
                      ]))

    iterator = util.InfDataLoader(dataset,
                                  batch_size=args.batch_size,
                                  num_workers=args.num_workers,
                                  shuffle=True,
                                  drop_last=True)

    # Set up output
    if not os.path.exists(args.out):
        os.makedirs(args.out)
    util.print_args(args, os.path.join(args.out, 'args.txt'))

    # Set up models
    g_params = {
        'latent_dim': args.latent_dim,
        'num_classes': args.num_classes,
        'channels': args.g_channels,
        'image_size': args.image_size,
        'spectral_norm': args.g_spectral_norm
    }
    d_params = {
        'num_classes': args.num_classes,
        'channels': args.d_channels,
        'dropout': args.d_dropout,
        'spectral_norm': args.d_spectral_norm,
        'pooling': args.d_pooling
    }
    netG = resnet.Generator(**g_params)
    netD = resnet.ACGANDiscriminator(**d_params)

    util.save_params(g_params, os.path.join(args.out, 'netG_params.pkl'))
    util.save_params(d_params, os.path.join(args.out, 'netD_params.pkl'))
    netG.to(device)
    netD.to(device)
    netG.apply(common.weights_init)
    netD.apply(common.weights_init)
    util.print_network(netG, 'G', os.path.join(args.out, 'netG_arch.txt'))
    util.print_network(netD, 'D', os.path.join(args.out, 'netD_arch.txt'))

    # Set up optimziers
    optimizerG = optim.Adam(netG.parameters(),
                            lr=args.g_lr,
                            betas=(args.beta1, args.beta2))
    optimizerD = optim.Adam(netD.parameters(),
                            lr=args.d_lr,
                            betas=(args.beta1, args.beta2))

    # Set up learning rate schedulers
    def lr_lambda(iteration):
        if args.num_iterations_decay > 0:
            lr = 1.0 - max(0,
                           (iteration + 1 -
                            (args.num_iterations - args.num_iterations_decay)
                            )) / float(args.num_iterations_decay)
        else:
            lr = 1.0
        return lr

    lr_schedulerG = optim.lr_scheduler.LambdaLR(optimizerG,
                                                lr_lambda=lr_lambda)
    lr_schedulerD = optim.lr_scheduler.LambdaLR(optimizerD,
                                                lr_lambda=lr_lambda)

    # Set up trainer
    trainter_params = {
        'iterator': iterator,
        'models': (netG, netD),
        'optimizers': (optimizerG, optimizerD),
        'gan_loss': args.gan_loss,
        'lr_schedulers': (lr_schedulerG, lr_schedulerD),
        'batch_size': args.batch_size,
        'g_bs_multiple': args.g_bs_multiple,
        'num_critic': args.num_critic,
        'factor_m': args.factor_m,
        'device': device
    }
    if args.trainer == 'acgan':
        Trainer = trainers.ACGANTrainer
        trainter_params.update({
            'lambdas': (args.lambda_gp, args.lambda_ct, args.lambda_cls_g,
                        args.lambda_cls_d)
        })
    elif args.trainer == 'cpgan':
        Trainer = trainers.CPGANTrainer
        trainter_params.update({
            'lambdas': (args.lambda_gp, args.lambda_ct, args.lambda_cls_g,
                        args.lambda_cls_d)
        })
    trainer = Trainer(**trainter_params)

    # Set up visualizer and logger
    visualizer = Visualizer(netG, args.vis_label_list, device, args.out,
                            args.num_samples, args.eval_batch_size)
    logger = Logger(args.out, 'loss')

    # Train
    while trainer.iteration < args.num_iterations:
        iter_start_time = time.time()
        trainer.update()

        if (args.display_interval > 0
                and trainer.iteration % args.display_interval == 0):
            t = (time.time() - iter_start_time) / args.batch_size
            logger.log(trainer.iteration, trainer.get_current_loss(), t)

        if (args.snapshot_interval > 0
                and trainer.iteration % args.snapshot_interval == 0):
            torch.save(
                netG.state_dict(),
                os.path.join(args.out, 'netG_iter_%d.pth' % trainer.iteration))
            torch.save(
                netD.state_dict(),
                os.path.join(args.out, 'netD_iter_%d.pth' % trainer.iteration))

        if (args.visualize_interval > 0
                and trainer.iteration % args.visualize_interval == 0):
            visualizer.visualize(trainer.iteration)
示例#3
0
def main(opt, reporter=None):
    writer = SummaryWriter()

    with open(writer.file_writer.get_logdir() + '/args.json', 'w') as f:
        json.dump(opt, f)

    if opt['experiment'] is None:
        opt['experiment'] = 'samples'
    os.system('mkdir {0}'.format(opt['experiment']))

    opt['manualSeed'] = random.randint(1, 10000)  # fix seed
    print("Random Seed: ", opt['manualSeed'])
    random.seed(opt['manualSeed'])
    torch.manual_seed(opt['manualSeed'])

    cudnn.benchmark = True

    if torch.cuda.is_available() and not opt['cuda']:
        print("WARNING: You have a CUDA device,"
              "so you should probably run with --cuda")

    if opt['dataset'] in ['imagenet', 'folder', 'lfw']:
        # folder dataset
        dataset = dset.ImageFolder(root=opt['dataroot'],
                                   transform=transforms.Compose([
                                       transforms.Scale(opt['imageSize']),
                                       transforms.CenterCrop(opt['imageSize']),
                                       transforms.ToTensor(),
                                       transforms.Normalize((0.5, 0.5, 0.5),
                                                            (0.5, 0.5, 0.5)),
                                   ]))
    elif opt['dataset'] == 'lsun':
        dataset = dset.LSUN(root=opt['dataroot'],
                            classes=['bedroom_train'],
                            transform=transforms.Compose([
                                transforms.Scale(opt['imageSize']),
                                transforms.CenterCrop(opt['imageSize']),
                                transforms.ToTensor(),
                                transforms.Normalize((0.5, 0.5, 0.5),
                                                     (0.5, 0.5, 0.5)),
                            ]))
    elif opt['dataset'] == 'cifar10':
        dataset = dset.CIFAR10(root=opt['dataroot'],
                               download=True,
                               transform=transforms.Compose([
                                   transforms.Scale(opt['imageSize']),
                                   transforms.ToTensor(),
                                   transforms.Normalize((0.5, 0.5, 0.5),
                                                        (0.5, 0.5, 0.5)),
                               ]))

    assert dataset
    dataloader = torch.utils.data.DataLoader(dataset,
                                             batch_size=opt['batchSize'],
                                             shuffle=True,
                                             num_workers=int(opt['workers']))

    ngpu = int(opt['ngpu'])
    nz = int(opt['nz'])
    ngf = int(opt['ngf'])
    ndf = int(opt['ndf'])
    nc = int(opt['nc'])
    n_extra_layers = int(opt['n_extra_layers'])

    # custom weights initialization called on netG and netD
    def weights_init(m):
        classname = m.__class__.__name__
        if classname.find('Conv') != -1:
            m.weight.data.normal_(0.0, 0.02)
        elif classname.find('BatchNorm') != -1:
            m.weight.data.normal_(1.0, 0.02)
            m.bias.data.fill_(0)

    if opt['noBN']:
        netG = dcgan.DCGAN_G_nobn(opt['imageSize'], nz, nc, ngf, ngpu,
                                  n_extra_layers)
    elif opt['type'] == 'mlp':
        netG = mlp.MLP_G(opt['imageSize'], nz, nc, ngf, ngpu)
    elif opt['type'] == 'resnet':
        netG = resnet.Generator(nz)
    else:
        netG = dcgan.DCGAN_G(opt['imageSize'], nz, nc, ngf, ngpu,
                             n_extra_layers)

    netG.apply(weights_init)
    print(netG)

    if opt['type'] == 'mlp':
        netD = mlp.MLP_D(opt['imageSize'], nz, nc, ndf, ngpu)
    elif opt['type'] == 'resnet':
        netD = resnet.Discriminator(nz)
    else:
        netD = dcgan.DCGAN_D(opt['imageSize'], nz, nc, ndf, ngpu,
                             n_extra_layers)
        netD.apply(weights_init)

    print(netD)

    inc_noise = torch.utils.data.TensorDataset(
        torch.randn(50000, nz, 1, 1).cuda())
    inc_noise_dloader = torch.utils.data.DataLoader(
        inc_noise, batch_size=opt['batchSize'])

    input = torch.FloatTensor(opt['batchSize'], 3, opt['imageSize'],
                              opt['imageSize'])
    noise = torch.FloatTensor(opt['batchSize'], nz, 1, 1)
    fixed_noise = torch.FloatTensor(opt['batchSize'], nz, 1, 1).normal_(0, 1)
    one = torch.FloatTensor([1])
    mone = one * -1

    if opt['cuda']:
        netD.cuda()
        netG.cuda()
        input = input.cuda()
        one, mone = one.cuda(), mone.cuda()
        noise, fixed_noise = noise.cuda(), fixed_noise.cuda()

    # setup optimizer
    if opt['adam']:
        optimizerD = optim.Adam(netD.parameters(),
                                lr=opt['lrD'],
                                betas=(opt['beta1'], opt['beta2']))
        optimizerG = optim.Adam(netG.parameters(),
                                lr=opt['lrG'],
                                betas=(opt['beta1'], opt['beta2']))
    else:
        optimizerD = optim.RMSprop(netD.parameters(), lr=opt['lrD'])
        optimizerG = optim.RMSprop(netG.parameters(), lr=opt['lrG'])

    var_weight = 0.5
    w = torch.tensor(
        [var_weight * (1 - var_weight)**i for i in range(9, -1, -1)]).cuda()

    gen_iterations = 0
    for epoch in range(opt['niter']):
        data_iter = iter(dataloader)
        i = 0
        while i < len(dataloader):
            # l_var = opt.l_var + (gen_iterations + 1)/3000
            l_var = opt['l_var']
            ############################
            # (1) Update D network
            ###########################
            for p in netD.parameters():  # reset requires_grad
                p.requires_grad = True

            # train the discriminator Diters times
            # if gen_iterations < 25 or gen_iterations % 500 == 0:
            if gen_iterations % 500 == 0:
                Diters = 100
            else:
                Diters = opt['Diters']

            j = 0
            while j < Diters and i < len(dataloader):
                j += 1

                # enforce constraint
                if not opt['var_constraint']:
                    for p in netD.parameters():
                        p.data.clamp_(opt['clamp_lower'], opt['clamp_upper'])

                data = data_iter.next()
                i += 1

                # train with real
                real_cpu, _ = data

                netD.zero_grad()
                batch_size = real_cpu.size(0)

                if opt['cuda']:
                    real_cpu = real_cpu.cuda()
                input.resize_as_(real_cpu).copy_(real_cpu)
                inputv = Variable(input)

                out_D_real = netD(inputv)
                errD_real = out_D_real.mean(0).view(1)

                if opt['var_constraint']:
                    vm_real = out_D_real.var(0)

                # train with fake
                noise.resize_(opt['batchSize'], nz, 1, 1).normal_(0, 1)
                with torch.no_grad():
                    noisev = Variable(noise)  # totally freeze netG
                    fake = netG(noisev).data
                inputv = fake
                out_D_fake = netD(inputv)
                errD_fake = out_D_fake.mean(0).view(1)

                if opt['var_constraint']:
                    vm_fake = out_D_fake.var(0)

                errD = errD_real - errD_fake

                loss = -((errD_real - errD_fake) - l_var * torch.exp(
                    torch.sqrt(torch.log(vm_real)**2 + torch.log(vm_fake)**2)))
                loss.backward()

                optimizerD.step()

                if opt['var_constraint']:
                    writer.add_scalars('train/variance', {
                        'real': vm_real.item(),
                        'fake': vm_fake.item()
                    },
                                       epoch * len(dataloader) + i)

            ############################
            # (2) Update G network
            ###########################
            for p in netD.parameters():
                p.requires_grad = False  # to avoid computation
            netG.zero_grad()
            # in case our last batch was the tail batch of the dataloader,
            # make sure we feed a full batch of noise
            noise.resize_(opt['batchSize'], nz, 1, 1).normal_(0, 1)
            noisev = Variable(noise)
            fake = netG(noisev)
            errG = -netD(fake).mean(0).view(1)
            errG.backward()
            optimizerG.step()
            gen_iterations += 1

            if torch.isnan(errG):
                raise ValueError("Loss is nan")

            ############################
            # Log Data
            ###########################
            print('[%d/%d][%d/%d][%d] Loss_D: %f Loss_G: %f Loss_D_real: %f'
                  ' Loss_D_fake %f' %
                  (epoch, opt['niter'], i, len(dataloader), gen_iterations,
                   errD.data[0], errG.data[0], errD_real.data[0],
                   errD_fake.data[0]))
            writer.add_scalar('train/critic', -errD.item(), gen_iterations)
            if gen_iterations % (500 * 64 / opt['batchSize']) == 0:
                real_cpu = real_cpu.mul(0.5).add(0.5)
                vutils.save_image(real_cpu,
                                  f'{opt["experiment"]}/real_samples.png')
                with torch.no_grad():
                    fake = netG(Variable(fixed_noise))
                fake.data = fake.data.mul(0.5).add(0.5)
                vutils.save_image(
                    fake.data, f'{opt["experiment"]}/'
                    f'fake_samples_{gen_iterations:010d}.png')
                writer.add_image(
                    'train/sample',
                    fake.data.mul(255).clamp(0, 255).byte().cpu().numpy(),
                    gen_iterations)

            ############################
            # (3) Compute Scores
            ############################
            if gen_iterations % (500 * 64 / opt['batchSize']) == 0:
                with torch.no_grad():
                    netG.eval()
                    samples = []
                    for (x, ) in inc_noise_dloader:
                        samples.append(netG(x))
                    netG.train()
                    samples = torch.cat(samples, dim=0).cpu()
                    samples = (samples - samples.mean()) / samples.std()

                score, _ = inception_score(samples.numpy(),
                                           cuda=True,
                                           resize=True,
                                           splits=10)
                writer.add_scalar('test/inception_50k', score, gen_iterations)
                # fids = fid_score(
                #     samples.permute(0, 2, 3,
                #                     1).mul(128).add(128).clamp(255).numpy(),
                #     'cifar10'
                # )
                # writer.add_scalar('test/fid_50k', fids, gen_iterations)
                if reporter:
                    reporter(inception=score, fid=0)

        # do checkpointing
        torch.save(netG.state_dict(),
                   f'{opt["experiment"]}/netG_epoch_{epoch}.pth')
        torch.save(netD.state_dict(),
                   f'{opt["experiment"]}/netD_epoch_{epoch}.pth')