Exemple #1
0
def run(output_path, gan_path, num_gen, if_fix):
    os.makedirs(output_path, exist_ok=True)
    index2strJson = json.load(open('zelda_index2str.json', 'r'))
    str2index = {}
    for key in index2strJson:
        str2index[index2strJson[key]] = key

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    netG = dcgan.DCGAN_G(32, 32, 8, 64, 1, 0)

    netG.load_state_dict(torch.load(gan_path))
    netG.to(device)

    with torch.no_grad():
        netG.eval()
        for i in tqdm.tqdm(range(num_gen)):
            fixed_noise = torch.FloatTensor(1, 32, 1, 1).normal_(0,
                                                                 1).to(device)
            output = netG(fixed_noise)
            im = output[:, :, :9, :13].cpu().numpy()
            numpyLvl = np.argmax(im, axis=1)[0]
            if if_fix:
                level = zelda_gan_output_to_txt(numpyLvl)
                new_level = fix_zelda_level(level)
                numpyLvl = get_integer_lvl(new_level, str2index)

            with open(os.path.join(output_path, '{}.json'.format(i)),
                      'w') as f:
                f.write(json.dumps(numpyLvl.tolist()))
def run(output_path,
        gan_experiment,
        cuda,
        gpu_id,
        if_fix):
    os.makedirs(output_path, exist_ok=True)
    index2strJson = json.load(open('zelda_index2str.json', 'r'))
    str2index = {}
    for key in index2strJson:
        str2index[index2strJson[key]] = key

    # now we need to setup lp function
    # Step 1. We translate our cplex model to matrices
    milp_program = Program(partial=True)
    cpx = milp_program.get_cplex_prob()  # get the cplex problem from the docplex model
    cpx.cleanup(epsilon=0.0001)
    c, G, h, A, b, var_type = cplex_utils.cplex_to_matrices(cpx)
    # _, inds = sympy.Matrix(A).T.rref()
    # A = A[np.array(inds)]
    # b = b[np.array(inds)]

    if cuda:
        G = torch.from_numpy(G).float().cuda(gpu_id)
        h = torch.from_numpy(h).float().cuda(gpu_id)
        A = torch.from_numpy(A).float().cuda(gpu_id)
        b = torch.from_numpy(b).float().cuda(gpu_id)
        Q = 2e-6 * torch.eye(A.shape[1]).cuda(gpu_id)
        Q = Q.type_as(G).cuda(gpu_id)
    else:
        G = torch.from_numpy(G)
        h = torch.from_numpy(h)
        A = torch.from_numpy(A)
        b = torch.from_numpy(b)
        Q = 2e-6 * torch.eye(A.shape[1])
        Q = Q.type_as(G)

    lp_function = LPFunction(QPSolvers.GUROBI, verbose=False)

    # netG = dcgan.DCGAN_G(32, 32, 8, 64, 1, 0)
    netG = dcgan.DCGAN_G(32, 32, 8, 64, 1, 0)
    netG_checkpoint = os.path.join(gan_experiment, 'netG_epoch_5499_999.pth')
    netG.load_state_dict(torch.load(netG_checkpoint))
    if cuda:
        netG.cuda(gpu_id)

    num_iter = 1000
    with torch.no_grad():
        netG.eval()
        for i in tqdm.tqdm(range(num_iter)):
            # first we use gan to generate the level
            noise = torch.FloatTensor(1, 32, 1, 1).normal_(0, 1)
            if cuda:
                noise = noise.cuda(gpu_id)
            output = netG(noise)
            pred_coefs = gan_out_2_coefs(output, c.size)
            x = lp_function(Q, pred_coefs, G, h, A, b)
            output2 = mip_sol_to_gan_out(output, x)
            im = output2.data[:, :, :9, :13].cpu().numpy()
            numpyLvl = np.argmax(im, axis=1)[0]
            if if_fix:
                level = zelda_gan_output_to_txt(numpyLvl)
                new_level = fix_zelda_level(level)
                numpyLvl = get_integer_lvl(new_level, str2index)

            with open(os.path.join(output_path, '{}.json'.format(i)), 'w') as f:
                f.write(json.dumps(numpyLvl.tolist()))
ndf = int(opt.ndf)

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)


netG = dcgan.DCGAN_G(map_size, nz, z_dims, ngf, ngpu, n_extra_layers)

netG.apply(weights_init)
if opt.netG != '':  # load checkpoint if needed
    netG.load_state_dict(torch.load(opt.netG))
# print(netG)

netD = dcgan.DCGAN_D(map_size, nz, z_dims, ndf, ngpu, n_extra_layers)
netD.apply(weights_init)

if opt.netD != '':
    netD.load_state_dict(torch.load(opt.netD))
# print(netD)

input = torch.FloatTensor(opt.batchSize, z_dims, map_size, map_size)
noise = torch.FloatTensor(opt.batchSize, nz, 1, 1)
def run(plot_range):
    f_h = 2
    f_w = 2
    human_root = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                              'data', 'zelda', 'Human_Json')
    human_lvls = get_valid_lvls(human_root)
    human_patterns = count_pattern_distribution(human_lvls, f_h, f_w)
    human_pattern_dist = count2dist(human_patterns)

    kl_lst = []
    average_path = []
    human_path = []
    duplicate_percentage = []
    valid_percentage = []
    valid_unique_percentage = []
    average_path_ratio = []
    for epoch_num in tqdm.tqdm(plot_range):
        gan_path = os.path.join(os.path.dirname(__file__), 'zelda_better_gan',
                                'netG_epoch_{}_999.pth'.format(epoch_num))

        # first generate 1000 levels
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        netG = dcgan.DCGAN_G(32, 32, 8, 64, 1, 0)
        netG.load_state_dict(torch.load(gan_path))
        netG.to(device)

        num_iter = 1000

        with torch.no_grad():
            netG.eval()

            noise = torch.FloatTensor(num_iter, 32, 1, 1).normal_(0,
                                                                  1).to(device)
            output = netG(noise)

            im = output[:, :, :9, :13].cpu().numpy()
            im = np.argmax(im, axis=1).astype(int).tolist()

        valid_generated_lvls = []
        costs = []
        # first only keep valid levels
        for lvl in im:
            ret = evaluate(lvl)
            if ret:
                valid_generated_lvls.append(lvl)
                costs.append(ret[1])

        # now it's time to compute kl divergence
        gan_patterns = count_pattern_distribution(valid_generated_lvls, f_h,
                                                  f_w)
        new_gan_patterns = {}
        for pattern in human_patterns:
            if pattern in gan_patterns:
                new_gan_patterns[pattern] = gan_patterns[pattern]
            else:
                new_gan_patterns[pattern] = 1e-5
        gan_pattern_dist = count2dist(new_gan_patterns)
        kl = compute_kl(human_pattern_dist, gan_pattern_dist)
        kl_lst.append(kl)

        average_cost = np.average(costs)
        average_path.append(average_cost)
        human_path.append(12.52)  # computed offline
        average_path_ratio.append(average_cost / 12.52)

        valid_percentage.append(len(valid_generated_lvls) / num_iter)
        num_duplicated, unique_lvls = compute_duplicated_lvls(
            valid_generated_lvls)
        valid_unique_percentage.append(len(unique_lvls) / num_iter)
        if len(valid_generated_lvls) > 0:
            duplicate_percentage.append(num_duplicated /
                                        len(valid_generated_lvls))
            # duplicate_percentage_x.append(epoch_num)
        else:
            duplicate_percentage.append(np.nan)

    fig = plt.figure()

    plt.plot(list(plot_range), kl_lst, label='KL Divergence')
    # plt.plot(list(plot_range), average_path, label='Average Path Length (GAN)')
    # plt.plot(list(plot_range), human_path, label='Average Path Length (Human)')
    plt.plot(list(plot_range),
             average_path_ratio,
             label='Average Path Length Ratio')
    plt.plot(list(plot_range), duplicate_percentage, label='Duplicated Levels')
    plt.plot(list(plot_range), valid_percentage, label='Valid Levels')
    plt.plot(list(plot_range),
             valid_unique_percentage,
             label='Valid and Unique Levels')
    # plt.axis('equal')
    plt.legend()

    plt.show()
def run(nz, ngf, ndf, batch_size, niter, lrD, lrG, beta1, cuda, ngpu, gpu_id,
        path_netG, path_netD, clamp_lower, clamp_upper, n_extra_layers,
        gan_experiment, adam, seed, lvl_data):
    os.makedirs(gan_experiment, exist_ok=True)

    random.seed(seed)
    torch.manual_seed(seed)

    cudnn.benchmark = True

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

    map_size = 32

    index2strJson = json.load(
        open(os.path.join(os.path.dirname(__file__), 'zelda_index2str.json'),
             'r'))
    str2index = {}
    for key in index2strJson:
        str2index[index2strJson[key]] = key

    # get all levels and store them in one numpy array
    np_lvls = []
    lvls = get_lvls(lvl_data)
    for lvl in lvls:
        numpyLvl = get_integer_lvl(lvl, str2index)
        np_lvls.append(numpyLvl)

    X = np.array(np_lvls)
    z_dims = len(index2strJson)

    num_batches = X.shape[0] / batch_size
    X_onehot = np.eye(z_dims, dtype='uint8')[X]
    X_onehot = np.rollaxis(X_onehot, 3, 1)
    X_train = np.zeros((X.shape[0], z_dims, map_size, map_size))
    X_train[:, 1, :, :] = 1.0
    X_train[:X.shape[0], :, :X.shape[1], :X.shape[2]] = X_onehot

    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)

    netG = dcgan.DCGAN_G(map_size, nz, z_dims, ngf, ngpu, n_extra_layers)
    netG.apply(weights_init)
    if path_netG != '':
        netG.load_state_dict(torch.load(path_netG))

    netD = dcgan.DCGAN_D(map_size, nz, z_dims, ndf, ngpu, n_extra_layers)
    netD.apply(weights_init)
    if path_netD != '':
        netD.load_state_dict(torch.load(path_netD))

    input = torch.FloatTensor(batch_size, z_dims, map_size, map_size)
    noise = torch.FloatTensor(batch_size, nz, 1, 1)
    fixed_noise = torch.FloatTensor(batch_size, nz, 1, 1).normal_(0, 1)
    one = torch.FloatTensor([1])
    mone = one * -1

    if cuda:
        netD.cuda(gpu_id)
        netG.cuda(gpu_id)
        input = input.cuda(gpu_id)
        one, mone = one.cuda(gpu_id), mone.cuda(gpu_id)
        noise, fixed_noise = noise.cuda(gpu_id), fixed_noise.cuda(gpu_id)

    # setup optimizer
    if adam:
        optimizerD = optim.Adam(netD.parameters(),
                                lr=lrD,
                                betas=(beta1, 0.999))
        optimizerG = optim.Adam(netG.parameters(),
                                lr=lrG,
                                betas=(beta1, 0.999))
        print("Using ADAM")
    else:
        optimizerD = optim.RMSprop(netD.parameters(), lr=lrD)
        optimizerG = optim.RMSprop(netG.parameters(), lr=lrG)

    for epoch in range(niter):
        X_train = X_train[torch.randperm(len(X_train))]

        ############################
        # (1) Update D network
        ###########################
        # for p in netD.parameters():  # reset requires_grad
        #     p.requires_grad = True  # they are set to False below in netG update
        # for p in netG.parameters():
        #     p.requires_grad = False
        i = 0
        total_errD_fake = 0
        total_errD_real = 0
        total_errG = 0
        while i < num_batches:  # len(dataloader):
            netD.zero_grad()
            # clamp parameters to a cube
            for p in netD.parameters():
                p.data.clamp_(clamp_lower, clamp_upper)

            data = X_train[i * batch_size:(i + 1) * batch_size]

            if cuda:
                real_cpu = torch.FloatTensor(data).cuda(gpu_id)
            else:
                real_cpu = torch.FloatTensor(data)

            input.resize_as_(real_cpu).copy_(real_cpu)

            errD_real = netD(input)
            errD_real.backward(one)
            total_errD_real += errD_real.item()

            # train with fake
            noise.resize_(batch_size, nz, 1, 1).normal_(0, 1)
            fake = netG(noise)
            errD_fake = netD(fake.detach())
            errD_fake.backward(mone)
            total_errD_fake += errD_fake.item()

            optimizerD.step()

            ############################
            # (2) Update G network
            ###########################
            netG.zero_grad()

            errG = netD(fake)
            errG.backward(one)
            total_errG += errG.item()
            optimizerG.step()

            i += 1
        average_errG = total_errG / num_batches
        average_errD_fake = total_errD_fake / num_batches
        average_errD_real = total_errD_real / num_batches

        print(
            '[%d/%d] Loss_G: %f Loss_D_real: %f Loss_D_fake %f' %
            (epoch, niter, average_errG, average_errD_real, average_errD_fake))

        if epoch % 10 == 9 or epoch == niter - 1:
            netG.eval()
            with torch.no_grad():
                fake = netG(fixed_noise)
                im = fake.cpu().numpy()[:, :, :9, :13]
                im = np.argmax(im, axis=1)
            with open(
                    '{0}/fake_level_epoch_{1}_{2}.json'.format(
                        gan_experiment, epoch, seed), 'w') as f:
                f.write(json.dumps(im[0].tolist()))
            torch.save(
                netG.state_dict(),
                '{0}/netG_epoch_{1}_{2}.pth'.format(gan_experiment, epoch,
                                                    seed))
def run(nz, ngf, ndf, batch_size, niter, lrD, lrG, beta1, cuda, ngpu, gpu_id,
        path_netG, path_netD, clamp_lower, clamp_upper, n_extra_layers,
        gan_experiment, mipaal_experiment, adam, seed, lvl_data):
    # Now we need to setup lpfunction
    shutil.rmtree(os.path.join(mipaal_experiment, 'runs'), ignore_errors=True)
    writer = SummaryWriter(log_dir=os.path.join(mipaal_experiment, 'runs'))
    models_dir = os.path.join(mipaal_experiment, 'models')
    os.makedirs(models_dir, exist_ok=True)
    # Step 1. We translate our cplex model to matrices
    milp_program = Program(partial=True)
    cpx = milp_program.get_cplex_prob(
    )  # get the cplex problem from the docplex model
    cpx.cleanup(epsilon=0.0001)
    c, G, h, A, b, var_type = cplex_utils.cplex_to_matrices(cpx)
    # _, inds = sympy.Matrix(A).T.rref()
    # A = A[np.array(inds)]
    # b = b[np.array(inds)]
    #
    # cpx = get_mip_program()
    # cpx.cleanup(epsilon=0.0001)
    # c, G, h, A, b, var_type = cplex_utils.cplex_to_matrices(cpx)
    if cuda:
        G = torch.from_numpy(G).float().cuda(gpu_id)
        h = torch.from_numpy(h).float().cuda(gpu_id)
        A = torch.from_numpy(A).float().cuda(gpu_id)
        b = torch.from_numpy(b).float().cuda(gpu_id)
        Q = 2e-6 * torch.eye(A.shape[1]).cuda(gpu_id)
        Q = Q.type_as(G).cuda(gpu_id)
    else:
        G = torch.from_numpy(G)
        h = torch.from_numpy(h)
        A = torch.from_numpy(A)
        b = torch.from_numpy(b)
        Q = 2e-6 * torch.eye(A.shape[1])
        Q = Q.type_as(G)
    if cuda:
        lp_function = LPFunction(QPSolvers.PDIPM_BATCHED, verbose=False)
    else:
        lp_function = LPFunction(QPSolvers.GUROBI, verbose=False)

    os.makedirs(gan_experiment, exist_ok=True)

    random.seed(seed)
    torch.manual_seed(seed)

    cudnn.benchmark = True  # enable cudnn auto-tuner for finding the optimial set of algorithms.

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

    map_size = 32

    index2strJson = json.load(
        open(os.path.join(os.path.dirname(__file__), 'zelda_index2str.json'),
             'r'))
    str2index = {}
    for key in index2strJson:
        str2index[index2strJson[key]] = key

    # get all levels and store them in one numpy array
    np_lvls = []
    lvls = get_lvls(lvl_data)
    for lvl in lvls:
        numpyLvl = get_integer_lvl(lvl, str2index)
        np_lvls.append(numpyLvl)

    X = np.array(np_lvls)
    z_dims = len(index2strJson)

    num_batches = X.shape[0] / batch_size
    X_onehot = np.eye(z_dims, dtype='uint8')[X]
    X_onehot = np.rollaxis(X_onehot, 3, 1)
    X_train = np.zeros((X.shape[0], z_dims, map_size, map_size))
    X_train[:, 1, :, :] = 1.0
    X_train[:X.shape[0], :, :X.shape[1], :X.shape[2]] = X_onehot

    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)

    netG = dcgan.DCGAN_G(map_size, nz, z_dims, ngf, ngpu, n_extra_layers)
    netG.apply(weights_init)
    if path_netG != '':
        netG.load_state_dict(torch.load(path_netG))

    netD = dcgan.DCGAN_D(map_size, nz, z_dims, ndf, ngpu, n_extra_layers)
    netD.apply(weights_init)
    if path_netD != '':
        netD.load_state_dict(torch.load(path_netD))

    input = torch.FloatTensor(batch_size, z_dims, map_size, map_size)
    noise = torch.FloatTensor(batch_size, nz, 1, 1)
    fixed_noise = torch.FloatTensor(batch_size, nz, 1, 1).normal_(0, 1)
    one = torch.FloatTensor([1])
    mone = one * -1

    if cuda:
        netD.cuda(gpu_id)
        netG.cuda(gpu_id)
        input = input.cuda(gpu_id)
        one, mone = one.cuda(gpu_id), mone.cuda(gpu_id)
        noise, fixed_noise = noise.cuda(gpu_id), fixed_noise.cuda(gpu_id)

    # setup optimizer
    if adam:
        optimizerD = optim.Adam(netD.parameters(),
                                lr=lrD,
                                betas=(beta1, 0.999))
        optimizerG = optim.Adam(netG.parameters(),
                                lr=lrG,
                                betas=(beta1, 0.999))
        print("Using ADAM")
    else:
        optimizerD = optim.RMSprop(netD.parameters(), lr=lrD)
        optimizerG = optim.RMSprop(netG.parameters(), lr=lrG)

    for epoch in range(niter):
        start_time = time.time()
        X_train = X_train[torch.randperm(
            len(X_train))]  # shuffle the training data

        ############################
        # (1) Update D network
        ###########################
        i = 0
        total_errD_fake = 0
        total_errD_real = 0
        total_errG = 0
        while i < num_batches:
            netD.zero_grad()
            # clamp parameters to a cube
            for p in netD.parameters():
                p.data.clamp_(clamp_lower, clamp_upper)
            data = X_train[i * batch_size:(i + 1) * batch_size]
            if cuda:
                real_cpu = torch.FloatTensor(data).cuda(gpu_id)
            else:
                real_cpu = torch.FloatTensor(data)
            input.resize_as_(real_cpu).copy_(real_cpu)
            errD_real = netD(input)
            errD_real.backward(one)
            total_errD_real += errD_real.item()

            # train with fake
            noise.resize_(batch_size, nz, 1, 1).normal_(0, 1)
            fake = netG(noise)
            pred_coefs = gan_out_2_coefs(fake, c.size, gpu_id, cuda)
            x = lp_function(Q, pred_coefs, G, h, A, b)
            fake2 = mip_sol_to_gan_out(fake, x)
            errD_fake = netD(fake2.detach())
            errD_fake.backward(mone)
            total_errD_fake += errD_fake.item()
            # i += 1
            optimizerD.step()

            ############################
            # (2) Update G network
            ###########################
            netG.zero_grad()
            errG = netD(fake2)
            errG.backward(one)
            total_errG += errG.item()
            optimizerG.step()
            i += 1

        average_errG = total_errG / num_batches
        average_errD_fake = total_errD_fake / num_batches
        average_errD_real = total_errD_real / num_batches

        end_time = time.time()

        print('[%d/%d] Loss_G: %f Loss_D_real: %f Loss_D_fake %f; time: [%d]' %
              (epoch, niter, average_errG, average_errD_real,
               average_errD_fake, end_time - start_time))

        if epoch % 100 == 99 or epoch == niter - 1:
            netG.eval()
            with torch.no_grad():
                fake = netG(fixed_noise)
                pred_coefs = gan_out_2_coefs(fake, c.size, gpu_id, cuda)
                x = lp_function(Q, pred_coefs, G, h, A, b)
                fake2 = mip_sol_to_gan_out(fake, x)
                im = fake2.data[:, :, :9, :13].cpu().numpy()
                im = np.argmax(im, axis=1)
            with open(
                    '{0}/fake_level_epoch_{1}_{2}.json'.format(
                        gan_experiment, epoch, seed), "w") as f:
                f.write(json.dumps(im[0].tolist()))
            torch.save(
                netG.state_dict(),
                '{0}/netG_epoch_{1}_{2}.pth'.format(gan_experiment, epoch,
                                                    seed))
            torch.save(
                netD.state_dict(),
                '{0}/netD_epoch_{1}_{2}.pth'.format(gan_experiment, epoch,
                                                    seed))