Beispiel #1
0
        model.load_state_dict(state_dict)
    else:
        model.embedding.weight.data.copy_(vocab.vectors)

    model = to_device(model)
    print(model)

    train(model, datasets, args)
    if args.save_model is not None:
        torch.save(model.state_dict(), args.save_model)

    if args.n_generated > 0:

        model.eval()

        samples, z, y_onehot = model.inference(n=args.n_generated)
        intent = y_onehot.data.max(1)[1].cpu().numpy()
        delexicalised = idx2word(samples, i2w=i2w, pad_idx=pad_idx)
        if args.input_type == 'delexicalised':
            labelling, utterance = surface_realisation(samples,
                                                       i2w=i2w,
                                                       pad_idx=pad_idx)
        print('----------GENERATED----------')
        for i in range(args.n_generated):
            print('Intent : ', i2int[intent[i]])
            print('Delexicalised : ', delexicalised[i])
        if args.input_type == 'delexicalised':
            for i in range(args.n_generated):
                print('Lexicalised : ', utterance[i] + '\n')

        run['generated'] = utterance
def main(args):
    # Image preprocessing
    transform = transforms.Compose([
        transforms.Resize((224, 224), Image.LANCZOS),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406),
                             (0.229, 0.224, 0.225))])

    # Load vocabulary wrapper
    with open(args.vocab_path, 'rb') as f:
        vocab = pickle.load(f)

    pad_idx = vocab.word2idx['<pad>']
    sos_idx = vocab.word2idx['<start>']
    eos_idx = vocab.word2idx['<end>']
    unk_idx = vocab.word2idx['<unk>']

    # Build the models
    model = CVAE(
        vocab_size=len(vocab),
        embedding_size=args.embedding_size,
        rnn_type=args.rnn_type,
        hidden_size=args.hidden_size,
        word_dropout=args.word_dropout,
        embedding_dropout=args.embedding_dropout,
        latent_size=args.latent_size,
        max_sequence_length=args.max_sequence_length,
        num_layers=args.num_layers,
        bidirectional=args.bidirectional,
        pad_idx=pad_idx,
        sos_idx=sos_idx,
        eos_idx=eos_idx,
        unk_idx=unk_idx
    )

    if not os.path.exists(args.load_checkpoint):
        raise FileNotFoundError(args.load_checkpoint)

    model.load_state_dict(torch.load(args.load_checkpoint))
    print("Model loaded from {}".format(args.load_checkpoint))

    model.to(device)
    model.eval()

    # Build data loader
    train_data_loader, valid_data_loader = get_loader(args.train_image_dir, args.val_image_dir,
                                                      args.train_caption_path, args.val_caption_path, vocab,
                                                      args.batch_size,
                                                      shuffle=True, num_workers=args.num_workers)

    f1 = open('{}/results/generated_captions.txt'.format(dataset_root_dir), 'w')
    f2 = open('{}/results/ground_truth_captions.txt'.format(dataset_root_dir), 'w')
    for i, (images, captions, lengths) in enumerate(valid_data_loader):
        images = images.to(device)

        sampled_ids, z = model.inference(n=args.batch_size, c=images)

        sampled_ids_batches = sampled_ids.cpu().numpy()  # (batch_size, max_seq_length)
        captions = captions.cpu().numpy()

        # Convert word_ids to words
        for j, sampled_ids in enumerate(sampled_ids_batches):
            sampled_caption = []
            for word_id in sampled_ids:
                word = vocab.idx2word[word_id]
                sampled_caption.append(word)
                if word == '<end>':
                    break
            generated_sentence = ' '.join(sampled_caption)
            generated_sentence = generated_sentence.rstrip()
            generated_sentence = generated_sentence.replace("\n", "")
            generated_sentence = "{0}\n".format(generated_sentence)
            if j == 0:
                print("RE: {}".format(generated_sentence))
            f1.write(generated_sentence)

        for g, ground_truth_ids in enumerate(captions):
            ground_truth_caption = []
            for word_id in ground_truth_ids:
                word = vocab.idx2word[word_id]
                ground_truth_caption.append(word)
                if word == '<end>':
                    break
            ground_truth_sentence = ' '.join(ground_truth_caption)
            ground_truth_sentence = ground_truth_sentence.rstrip()
            ground_truth_sentence = ground_truth_sentence.replace("\n", "")
            ground_truth_sentence = "{0}\n".format(ground_truth_sentence)
            if g == 0:
                print("GT: {}".format(ground_truth_sentence))
            f2.write(ground_truth_sentence)
        if i % 10 == 0:
            print("This is the {0}th batch".format(i))
    f1.close()
    f2.close()
Beispiel #3
0
class CVAEInterface():
    def __init__(self, run_id=1, output_path="", env_path_root=""):
        super().__init__()
        self.cvae = CVAE(run_id=run_id)
        self.device = torch.device('cuda' if CUDA_AVAILABLE else 'cpu')
        self.output_path = output_path
        self.env_path_root = env_path_root

        if self.output_path is not None:
            if os.path.exists(self.output_path):
                shutil.rmtree(self.output_path)
            os.mkdir(self.output_path)

    def load_dataset(self, dataset_root, data_type="arm", mode="train"):
        assert (data_type == "both" or data_type == "arm"
                or data_type == "base")
        assert (mode == "train" or mode == "test")
        # Should show different count and path for different modes
        print("Loading {} dataset for mode : {}, path : {}".format(
            data_type, mode, dataset_root))
        self.data_type = data_type

        paths_dataset = PathsDataset(type="FULL_STATE")
        c_test_dataset = PathsDataset(type="CONDITION_ONLY")
        env_dir_paths = os.listdir(dataset_root)
        # Get all C vars to test sample generation on each
        all_condition_vars = []
        for env_dir_index in filter(lambda f: f[0].isdigit(), env_dir_paths):
            env_paths_file = os.path.join(dataset_root, env_dir_index,
                                          "data_{}.txt".format(data_type))
            env_paths = np.loadtxt(env_paths_file)
            # 4 to 16
            if IGNORE_START:
                start = env_paths[:, X_DIM:2 * X_DIM]
                samples = env_paths[:, :X_DIM]
                euc_dist = np.linalg.norm(start - samples, axis=1)
                far_from_start = np.where(euc_dist > 5.0)
                print(far_from_start)
                env_paths = env_paths[far_from_start[0], :]
                condition_vars = env_paths[:, 2 * X_DIM:2 * X_DIM + C_DIM]
            else:
                if mode == "train":
                    # Testing, less points near start to reduce them in sampled output
                    start = env_paths[:, X_DIM:X_DIM + POINT_DIM]
                    samples = env_paths[:, :X_DIM]
                    euc_dist = np.linalg.norm(start - samples, axis=1)
                    far_from_start = np.where(euc_dist > 2.0)
                    # print(far_from_start)
                    env_paths = env_paths[far_from_start[0], :]

                condition_vars = env_paths[:, X_DIM:X_DIM + C_DIM]
            # print(env_paths.shape)
            # Stuff for train dataloader
            # Take only required elements
            # env_paths = env_paths[:, :X_DIM + C_DIM]
            env_paths = np.hstack((env_paths[:, :X_DIM], condition_vars))
            # Uniquify to remove duplicates
            env_paths = np.unique(env_paths, axis=0)
            env_index = np.empty((env_paths.shape[0], 1))
            env_index.fill(env_dir_index)
            data = np.hstack((env_index, env_paths))
            paths_dataset.add_env_paths(data.tolist())

            # Stuff for test dataloader
            env_index = np.empty((condition_vars.shape[0], 1))
            env_index.fill(env_dir_index)
            data = np.hstack((env_index, condition_vars))
            all_condition_vars += data.tolist()
            print("Added {} states from {} environment".format(
                env_paths.shape[0], env_dir_index))

        dataloader = DataLoader(paths_dataset,
                                batch_size=TRAIN_BATCH_SIZE,
                                shuffle=True)

        if data_type != "both":

            # Depending on which dataset is being loaded, set the right variables
            if mode == "train":
                self.train_dataloader = dataloader
                self.train_paths_dataset = paths_dataset
            elif mode == "test":
                self.test_condition_vars = np.unique(all_condition_vars,
                                                     axis=0)
                print("Unique test conditions count : {}".format(
                    self.test_condition_vars.shape[0]))
                # Tile condition variables to predict given number of samples for x
                all_condition_vars_tile = np.repeat(self.test_condition_vars,
                                                    TEST_SAMPLES, 0)
                c_test_dataset.add_env_paths(all_condition_vars_tile.tolist())
                c_test_dataloader = DataLoader(c_test_dataset,
                                               batch_size=TEST_BATCH_SIZE,
                                               shuffle=False)
                self.test_dataloader = c_test_dataloader
        else:
            arm_test_dataset = PathsDataset(type="CONDITION_ONLY")
            base_test_dataset = PathsDataset(type="CONDITION_ONLY")

            all_condition_vars = np.array(all_condition_vars)
            self.test_condition_vars = np.delete(all_condition_vars, [4, 5],
                                                 axis=1)
            self.test_condition_vars = np.unique(self.test_condition_vars,
                                                 axis=0)
            print("Unique test conditions count : {}".format(
                self.test_condition_vars.shape[0]))
            # print(self.test_condition_vars)
            arm_condition_vars = np.insert(self.test_condition_vars,
                                           2 * POINT_DIM,
                                           1,
                                           axis=1)
            arm_condition_vars = np.insert(arm_condition_vars,
                                           2 * POINT_DIM,
                                           0,
                                           axis=1)

            arm_condition_vars = np.repeat(arm_condition_vars, TEST_SAMPLES, 0)
            arm_test_dataset.add_env_paths(arm_condition_vars.tolist())
            arm_test_dataloader = DataLoader(arm_test_dataset,
                                             batch_size=TEST_BATCH_SIZE,
                                             shuffle=False)

            base_condition_vars = np.insert(self.test_condition_vars,
                                            2 * POINT_DIM,
                                            0,
                                            axis=1)
            base_condition_vars = np.insert(base_condition_vars,
                                            2 * POINT_DIM,
                                            1,
                                            axis=1)

            base_condition_vars = np.repeat(base_condition_vars, TEST_SAMPLES,
                                            0)
            base_test_dataset.add_env_paths(base_condition_vars.tolist())
            base_test_dataloader = DataLoader(base_test_dataset,
                                              batch_size=TEST_BATCH_SIZE,
                                              shuffle=False)

            if mode == "train":
                self.train_dataloader = dataloader
            elif mode == "test":
                self.arm_test_dataloader = arm_test_dataloader
                self.base_test_dataloader = base_test_dataloader

    def visualize_train_data(self, num_conditions=1):
        # Pick a random condition
        # Find all states for that condition
        # Plot them
        print("Plotting input data for {} random conditions".format(
            num_conditions))
        all_input_paths = np.array(self.train_paths_dataset.paths)[:, 1:]
        env_ids = np.array(self.train_paths_dataset.paths)[:, :1]
        # print(all_input_paths[0,:])
        for c_i in range(num_conditions):
            rand_index = np.random.randint(0, all_input_paths.shape[0])
            condition = all_input_paths[rand_index, 2:]
            env_id = env_ids[rand_index, 0]
            # print(condition)
            # condition_samples = np.argwhere(all_input_paths[:,2:] == condition)
            # indices = np.where(all_input_paths[:,2:] == condition)
            # Find all samples corresponding to this condition
            indices = np.where(
                np.isin(all_input_paths[:, 2:], condition).all(axis=1))[0]
            # print(indices)
            x = all_input_paths[indices, :2]
            fig = self.plot(x, condition, env_id=env_id)
            self.cvae.tboard.add_figure('train_data/condition_{}'.format(c_i),
                                        fig, 0)
            # print(all_input_paths[indices,:])
        self.cvae.tboard.flush()

    def visualize_map(self, env_id):
        path = "{}/{}.txt".format(self.env_path_root, int(env_id))
        plt.title('Environment - {}'.format(env_id))
        with open(path, "r") as f:
            line = f.readline()
            while line:
                line = line.split(" ")
                # print(line)
                if "wall" in line[0] or "table" in line[0]:
                    x = float(line[1])
                    y = float(line[2])
                    l = float(line[4])
                    b = float(line[5])
                    rect = Rectangle((x - l / 2, y - b / 2), l, b)
                    plt.gca().add_patch(rect)

                line = f.readline()
        plt.draw()

    def plot(self, x, c, env_id=None, suffix=0, write_file=False, show=False):
        '''
            Plot samples and environment - from train input or predicted output
        '''
        # print(c)
        if IGNORE_START:
            goal = c[0:2]
        else:
            start = c[0:2]
            goal = c[2:4]
        # For given conditional, plot the samples
        fig1 = plt.figure(figsize=(10, 6), dpi=80)
        # ax1 = fig1.add_subplot(111, aspect='equal')
        plt.scatter(x[:, 0], x[:, 1], color="green", s=70, alpha=0.1)
        if IGNORE_START == False:
            plt.scatter(start[0], start[1], color="blue", s=70, alpha=0.6)
        plt.scatter(goal[0], goal[1], color="red", s=70, alpha=0.6)
        if env_id is not None:
            self.visualize_map(env_id)
            # wall_locs = c[4:]
            # i = 0
            # while i < wall_locs.shape[0]:
            #     plt.scatter(wall_locs[i], wall_locs[i+1], color="green", s=70, alpha=0.6)
            #     i = i + 2

        plt.xlabel('x')
        plt.ylabel('y')
        plt.xlim(0, X_MAX)
        plt.ylim(0, Y_MAX)
        if write_file:
            plt.savefig('{}/gen_points_fig_{}.png'.format(
                self.output_path, suffix))
            np.savetxt('{}/gen_points_{}.txt'.format(self.output_path, suffix),
                       x,
                       fmt="%.2f",
                       delimiter=',')
            np.savetxt('{}/start_goal_{}.txt'.format(self.output_path, suffix),
                       np.vstack((start, goal)),
                       fmt="%.2f",
                       delimiter=',')
        if show:
            plt.show()
        # plt.close(fig1)
        return fig1

    def load_saved_cvae(self, decoder_path):
        print("Loading saved CVAE")
        self.cvae.load_decoder(decoder_path)

        # base_cvae = CVAE(run_id=run_id)
        # base_decoder_path = 'experiments/cvae/base/decoder-final.pkl'
        # base_cvae.load_decoder(base_decoder_path)

        # for iteration, batch in enumerate(dataloader):
    def test_single(self,
                    env_id,
                    sample_size=1000,
                    c_test=None,
                    visualize=True):
        self.cvae.eval()
        c_test_gpu = torch.from_numpy(c_test).float().to(self.device)
        c_test_gpu = torch.unsqueeze(c_test_gpu, dim=0)
        x_test = self.cvae.inference(sample_size=sample_size, c=c_test_gpu)
        x_test = x_test.detach().cpu().numpy()

        if visualize:
            self.plot(x_test,
                      c_test,
                      env_id=env_id,
                      show=False,
                      write_file=True,
                      suffix=0)
        return x_test

    def test(self, epoch, dataloader, write_file=False, suffix=""):

        x_test_predicted = []
        self.cvae.eval()
        for iteration, batch in enumerate(dataloader):
            # print(batch)
            c_test_data = batch['condition'].float().to(self.device)
            # print(c_test_data[0,:])
            x_test = self.cvae.batch_inference(c=c_test_data)
            x_test_predicted += x_test.detach().cpu().numpy().tolist()
            # print(x_test.shape)
            if iteration % LOG_INTERVAL == 0 or iteration == len(
                    dataloader) - 1:
                print(
                    "Test Epoch {:02d}/{:02d} Batch {:04d}/{:d}, Iteration {}".
                    format(epoch, num_epochs, iteration,
                           len(dataloader) - 1, iteration))

        x_test_predicted = np.array(x_test_predicted)
        # print(x_test_predicted.shape)
        # Draw plot for each unique condition
        for c_i in range(self.test_condition_vars.shape[0]):
            x_test = x_test_predicted[c_i * TEST_SAMPLES:(c_i + 1) *
                                      TEST_SAMPLES]
            # Fine because c_test is used only for plotting, we dont need arm/base label here
            c_test = self.test_condition_vars[c_i, 1:]
            env_id = self.test_condition_vars[c_i, 0]
            # print(self.test_condition_vars[c_i,:])
            fig = self.plot(x_test,
                            c_test,
                            env_id=env_id,
                            suffix=c_i,
                            write_file=write_file)
            self.cvae.tboard.add_figure(
                'test_epoch_{}/condition_{}_{}'.format(epoch, c_i, suffix),
                fig, 0)
            if c_i % LOG_INTERVAL == 0:
                print("Plotting condition : {}".format(c_i))
        self.cvae.tboard.flush()

        # for c_i in range(c_test_data.shape[0]):
        #     c_test = c_test_data[c_i,:]
        #     c_test_gpu = torch.from_numpy(c_test).float().to(device)

        #     x_test = cvae_model.inference(n=TEST_SAMPLES, c=c_test_gpu)
        #     x_test = x_test.detach().cpu().numpy()
        #     fig = plot(x_test, c_test)
        #     cvae_model.tboard.add_figure('test_epoch_{}/condition_{}'.format(epoch, c_i), fig, 0)

        #     if c_i % 50 == 0:
        #         print("Epoch : {}, Testing condition count : {} ".format(epoch, c_i))

    def train(self,
              run_id=1,
              num_epochs=1,
              initial_learning_rate=0.001,
              weight_decay=0.0001):

        optimizer = torch.optim.Adam(self.cvae.parameters(),
                                     lr=initial_learning_rate,
                                     weight_decay=weight_decay)
        for epoch in range(num_epochs):
            for iteration, batch in enumerate(self.train_dataloader):
                # print(batch['condition'][0,:])
                self.cvae.train()
                x = batch['state'].float().to(self.device)
                c = batch['condition'].float().to(self.device)
                recon_x, mean, log_var, z = self.cvae(x, c)
                # print(recon_x.shape)

                loss = self.cvae.loss_fn(recon_x, x, mean, log_var)

                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

                counter = epoch * len(self.train_dataloader) + iteration
                if iteration % LOG_INTERVAL == 0 or iteration == len(
                        self.train_dataloader) - 1:
                    print(
                        "Train Epoch {:02d}/{:02d} Batch {:04d}/{:d}, Iteration {}, Loss {:9.4f}"
                        .format(epoch, num_epochs, iteration,
                                len(self.train_dataloader) - 1, counter,
                                loss.item()))
                    self.cvae.tboard.add_scalar('train/loss', loss.item(),
                                                counter)

                    # cvae.eval()
                    # c_test = c[0,:]
                    # x_test = cvae.inference(n=TEST_SAMPLES, c=c_test)
                    # x_test = x_test.detach().cpu().numpy()
                    # fig = plot(x_test, c_test)
                    # cvae.tboard.add_figure('test/samples', fig, counter)

            if epoch % TEST_INTERVAL == 0 or epoch == num_epochs - 1:
                # Test CVAE for all c by drawing samples
                if self.data_type != "both":
                    self.test(epoch, self.test_dataloader)
                else:
                    self.test(epoch, self.arm_test_dataloader, suffix="arm")
                    self.test(epoch, self.base_test_dataloader, suffix="base")

            if epoch % SAVE_INTERVAL == 0 and epoch > 0:
                self.cvae.save_model_weights(counter)

        self.cvae.save_model_weights('final')