コード例 #1
0
    def __init__(self, trainer=None):
        """
        :param trainer: An implementation of NeuralNetworkTrainer that will be used to train both networks.
        Read from config if None.
        """
        if trainer is not None:
            self.trainer = trainer
        else:
            self.cc = ConfigurationContainer.instance()
            dataloader = self.cc.create_instance(
                self.cc.settings['dataloader']['dataset_name'])
            network_factory = self.cc.create_instance(
                self.cc.settings['network']['name'],
                dataloader.n_input_neurons)
            self.trainer = self.cc.create_instance(
                self.cc.settings['trainer']['name'], dataloader,
                network_factory)

        self._logger.info("Parameters: {}".format(self.cc.settings))

        if is_cuda_enabled():
            self._logger.info(
                "CUDA is supported on this device and will be used.")
        else:
            self._logger.info("CUDA is not supported on this device.")
コード例 #2
0
    def compute_loss_against(self, opponent, input, labels = None, alpha = None, beta = None, iter = None, log_class_distribution = False,):
        FloatTensor = torch.cuda.FloatTensor if is_cuda_enabled() else torch.FloatTensor
        LongTensor = torch.cuda.LongTensor if is_cuda_enabled() else torch.LongTensor
        batch_size = input.size(0)
        # print(batch_size)
        # print(input.size(1))
        # print('batch size')
        # print(batch_size)
        real_labels = to_pytorch_variable(torch.ones(batch_size))  # label all generator images 1 (real)

        z = noise(batch_size, self.data_size)  # dims: batch size x data_size

        labels = LongTensor(
            np.random.randint(0, self.num_classes, batch_size))  # random labels between 0 and 9, output of shape batch_size
        labels = labels.view(-1, 1)
        labels_onehot = torch.FloatTensor(batch_size, self.num_classes)
        labels_onehot.zero_()
        labels_onehot.scatter_(1, labels, 1)
        # print(labels_onehot)


        labels = to_pytorch_variable(labels_onehot.type(FloatTensor))
        # print(labels)
        # print(self.label_emb(labels))
        # concatenate z and labels here before passing into generator net

        gen_input = torch.cat((labels, z), -1)
        # print(gen_input)
        # print('gen input shape')
        # print(gen_input.shape)
        fake_images = self.net(gen_input)
        # print('fake images shape')
        # print(fake_images.shape)
        # fake_images = fake_images.view(fake_images.size(0), *)

        dis_input = torch.cat((fake_images, labels), -1)  # discriminator training data input
        # concatenate fake_images and labels here before passing into discriminator net
        outputs = opponent.net(dis_input).view(-1)  # view(-1) flattens tensor

        return self.loss_function(outputs,
                                  real_labels), fake_images  # loss function evaluated discriminator output vs. 1 (generator trying to get discriminator output to be 1)
コード例 #3
0
ファイル: competetive_net.py プロジェクト: swalpa/mustang
    def __init__(self, loss_function, net, data_size, optimize_bias=True):
        self.data_size = data_size
        self.loss_function = loss_function
        self.net = net.cuda() if is_cuda_enabled() else net
        self.optimize_bias = optimize_bias

        self.n_weights = np.sum([l.weight.numel() for l in self.net if hasattr(l, 'weight')])
        # Calculate split positions; cumulative sum needed because split() expects positions, not chunk sizes
        self.split_positions_weights = [l.weight.numel() for l in self.net if hasattr(l, 'weight')]

        if optimize_bias:
            self.split_positions_biases = [l.bias.numel() for l in self.net if hasattr(l, 'bias')]
コード例 #4
0
    def __init__(self, loss_function, net, data_size, optimize_bias=True):
        self.data_size = data_size
        self.net = net.cuda() if is_cuda_enabled() else net
        self.optimize_bias = optimize_bias

        self._logger = logging.getLogger(__name__)

        self.loss_function = loss_function
        if self.loss_function.__class__.__name__ == 'MustangsLoss':
            self.loss_function.set_network_name(self.name)

        try:
            self.n_weights = np.sum([l.weight.numel() for l in self.net if hasattr(l, 'weight')])
            # Calculate split positions; cumulative sum needed because split() expects positions, not chunk sizes
            self.split_positions_weights = [l.weight.numel() for l in self.net if hasattr(l, 'weight')]

            if optimize_bias:
                self.split_positions_biases = [l.bias.numel() for l in self.net if hasattr(l, 'bias')]
        except Exception as e:
            print(e)
コード例 #5
0
class LipizzanerWGANTrainer(LipizzanerGANTrainer):
    """
    Distributed, asynchronous trainer for coevolutionary GANs. Uses the more sophisticated Wasserstein GAN.
    Original source code: from https://github.com/martinarjovsky/WassersteinGAN/
    """

    gen_iterations = 0
    real_labels = torch.FloatTensor(
        [1]).cuda() if is_cuda_enabled() else torch.FloatTensor([1])
    fake_labels = real_labels * -1

    def update_genomes(self, population_attacker, population_defender,
                       input_var, loaded, data_iterator):
        if population_attacker.population_type == TYPE_DISCRIMINATOR:
            return self._update_discriminators(population_attacker,
                                               population_defender, input_var,
                                               loaded, data_iterator)
        elif population_attacker.population_type == TYPE_GENERATOR:
            return self._update_generators(population_attacker,
                                           population_defender, input_var)
        else:
            raise Exception('Population type not explicitely set.')

    def _update_discriminators(self, population_attacker, population_defender,
                               input_var, loaded, data_iterator):

        batch_size = input_var.size(0)
        # Randomly pick one only, referred from asynchronous_ea_trainer
        generator = random.choice(population_defender.individuals)

        for i, discriminator in enumerate(population_attacker.individuals):
            if i < len(population_attacker.individuals) - 1:
                # https://stackoverflow.com/a/42132767
                # Perform deep copy first instead of directly updating iterator passed in
                data_iterator, curr_iterator = tee(data_iterator)
            else:
                # Directly update the iterator with the last individual only, so that
                # every individual can learn from the full batch
                curr_iterator = data_iterator

            # Use temporary batch variable for each individual
            # so that every individual can learn from the full batch
            curr_batch_number = self.batch_number
            optimizer = self._get_optimizer(discriminator)

            # Train the discriminator Diters times
            if self.gen_iterations < 25 or self.gen_iterations % 500 == 0:
                discriminator_iterations = 100
            else:
                discriminator_iterations = DISCRIMINATOR_STEPS

            j = 0
            while j < discriminator_iterations and curr_batch_number < len(
                    loaded):
                if j > 0:
                    input_var = to_pytorch_variable(
                        self.dataloader.transpose_data(next(curr_iterator)[0]))
                j += 1

                # Train with real data
                discriminator.genome.net.zero_grad()
                error_real = discriminator.genome.net(input_var)
                error_real = error_real.mean(0).view(1)
                error_real.backward(self.real_labels)

                # Train with fake data
                z = noise(batch_size, generator.genome.data_size)
                z.volatile = True
                fake_data = Variable(generator.genome.net(z).data)
                loss = discriminator.genome.net(fake_data).mean(0).view(1)
                loss.backward(self.fake_labels)
                optimizer.step()

                # Clamp parameters to a cube
                for p in discriminator.genome.net.parameters():
                    p.data.clamp_(CLAMP_LOWER, CLAMP_UPPER)

                curr_batch_number += 1

            discriminator.optimizer_state = optimizer.state_dict()
        # Update the final batch_number to class variable after all individuals are updated
        self.batch_number = curr_batch_number

        return input_var

    def _update_generators(self, population_attacker, population_defender,
                           input_var):

        batch_size = input_var.size(0)
        # Randomly pick one only, referred from asynchronous_ea_trainer
        discriminator = random.choice(population_defender.individuals)

        for generator in population_attacker.individuals:
            optimizer = self._get_optimizer(generator)

            # Avoid computation
            for p in discriminator.genome.net.parameters():
                p.requires_grad = False

            generator.genome.net.zero_grad()
            # in case our last batch was the tail batch of the dataloader,
            # make sure we feed a full batch of noise
            z = noise(batch_size, generator.genome.data_size)
            fake_data = generator.genome.net(z)
            error = discriminator.genome.net(fake_data).mean(0).view(1)
            error.backward(self.real_labels)
            optimizer.step()

            generator.optimizer_state = optimizer.state_dict()

            for p in discriminator.genome.net.parameters():
                p.requires_grad = True

        self.gen_iterations += 1
        return input_var

    @staticmethod
    def _get_optimizer(individual):
        optimizer = torch.optim.RMSprop(individual.genome.net.parameters(),
                                        lr=individual.learning_rate)

        # Restore previous state dict, if available
        if individual.optimizer_state is not None:
            optimizer.load_state_dict(individual.optimizer_state)
        return optimizer
コード例 #6
0
class LipizzanerWGANTrainer(LipizzanerGANTrainer):
    """
    Distributed, asynchronous trainer for coevolutionary GANs. Uses the more sophisticated Wasserstein GAN.
    Original source code: from https://github.com/martinarjovsky/WassersteinGAN/
    """

    gen_iterations = 0
    real_labels = torch.FloatTensor([1]).cuda() if is_cuda_enabled() else torch.FloatTensor([1])
    fake_labels = real_labels * -1

    def update_genomes(self, population_attacker, population_defender, input_var, loaded, data_iterator, defender_weights):
        if population_attacker.population_type == TYPE_DISCRIMINATOR:
            return self._update_discriminators(population_attacker, population_defender, input_var, loaded,
                                               data_iterator, defender_weights)
        elif population_attacker.population_type == TYPE_GENERATOR:
            return self._update_generators(population_attacker, population_defender, input_var, defender_weights)
        else:
            raise Exception('Population type not explicitely set.')

    def _update_discriminators(self, population_attacker, population_defender, input_var, loaded, data_iterator, defender_weights):

        batch_size = input_var.size(0)

        for discriminator in population_attacker.individuals:
            weights = [self.get_weight(defender, defender_weights) for defender in population_defender.individuals]
            weights /= np.sum(weights)
            generator = np.random.choice(population_defender.individuals, p=weights)
            optimizer = self._get_optimizer(discriminator)

            # Train the discriminator Diters times
            if self.gen_iterations < 25 or self.gen_iterations % 500 == 0:
                discriminator_iterations = 100
            else:
                discriminator_iterations = DISCRIMINATOR_STEPS

            j = 0
            while j < discriminator_iterations and self.batch_number < len(loaded):
                if j > 0:
                    input_var = to_pytorch_variable(self.dataloader.transpose_data(next(data_iterator)[0]))
                j += 1

                # Train with real data
                discriminator.genome.net.zero_grad()
                error_real = discriminator.genome.net(input_var)
                error_real = error_real.mean(0).view(1)
                error_real.backward(self.real_labels)

                # Train with fake data
                z = noise(batch_size, generator.genome.data_size)
                z.volatile = True
                fake_data = Variable(generator.genome.net(z).data)
                loss = discriminator.genome.net(fake_data).mean(0).view(1)
                loss.backward(self.fake_labels)
                optimizer.step()

                # Clamp parameters to a cube
                for p in discriminator.genome.net.parameters():
                    p.data.clamp_(CLAMP_LOWER, CLAMP_UPPER)

                self.batch_number += 1

            discriminator.optimizer_state = optimizer.state_dict()

        return input_var

    def _update_generators(self, population_attacker, population_defender, input_var, defender_weights):

        batch_size = input_var.size(0)

        for generator in population_attacker.individuals:
            weights = [self.get_weight(defender, defender_weights) for defender in population_defender.individuals]
            weights /= np.sum(weights)
            discriminator = np.random.choice(population_defender.individuals, p=weights)
            optimizer = self._get_optimizer(generator)

            # Avoid computation
            for p in discriminator.genome.net.parameters():
                p.requires_grad = False

            generator.genome.net.zero_grad()
            # in case our last batch was the tail batch of the dataloader,
            # make sure we feed a full batch of noise
            z = noise(batch_size, generator.genome.data_size)
            fake_data = generator.genome.net(z)
            error = discriminator.genome.net(fake_data).mean(0).view(1)
            error.backward(self.real_labels)
            optimizer.step()

            generator.optimizer_state = optimizer.state_dict()

            for p in discriminator.genome.net.parameters():
                p.requires_grad = True

        self.gen_iterations += 1
        return input_var

    @staticmethod
    def _get_optimizer(individual):
        optimizer = torch.optim.RMSprop(individual.genome.net.parameters(),
                                        lr=individual.learning_rate)

        # Restore previous state dict, if available
        if individual.optimizer_state is not None:
            optimizer.load_state_dict(individual.optimizer_state)
        return optimizer
コード例 #7
0
    def __init__(self, generator_population, weights, n_samples, mixture_generator_samples_mode, z=None):
        """
        Creates samples from a mixture of generators, with sample probability defined given a random noise vector
        sampled from the latent space by a weights vector

        :param generator_population: Population of generators that will be used to create the images
        :param weights: Dictionary that maps generator IDs to weights, e.g. {'127.0.0.1:5000': 0.8, '127.0.0.1:5001': 0.2}
        :param n_samples: Number of samples that will be generated
        :param mixture_generator_samples_mode:
        :param z: Noise vector from latent space. If it is not given it generates a new one
        """
        self.n_samples = n_samples
        self.individuals = sorted(generator_population.individuals, key=lambda x: x.source)
        for individual in self.individuals:
            individual.genome.net.eval()
        self.data = []

        self.cc = ConfigurationContainer.instance()

        weights = collections.OrderedDict(sorted(weights.items()))
        weights = {k: v for k, v in weights.items() if any([i for i in self.individuals if i.source == k])}
        weights_np = np.asarray(list(weights.values()))

        if np.sum(weights_np) != 1:
            weights_np = weights_np / np.sum(weights_np).astype(float)    # A bit of patching, but normalize it again

        if mixture_generator_samples_mode == 'independent_probability':
            self.gen_indices = np.random.choice(len(self.individuals), n_samples, p=weights_np.tolist())
        elif mixture_generator_samples_mode == 'exact_proportion':
            # Does not perform checking here if weights_np.tolist() sum up to one
            # There will be some trivial error if prob*n_samples is not integer for prob in weights_np.tolist()
            self.gen_indices = [
                i for gen_idx, prob in enumerate(weights_np.tolist()) for i in [gen_idx] * math.ceil(n_samples * prob)
            ]
            np.random.shuffle(self.gen_indices)
            self.gen_indices = self.gen_indices[:n_samples]
        else:
            raise NotImplementedError(
                "Invalid argument for mixture_generator_samples_mode: {}".format(mixture_generator_samples_mode)
            )

        num_classes = self.individuals[0].genome.num_classes if hasattr(self.individuals[0].genome, 'num_classes') \
                                                                and self.individuals[0].genome.num_classes != 0 else 0

        if z is None:
            z = noise(n_samples, self.individuals[0].genome.data_size)

            if num_classes != 0 and self.cc.settings["network"]["name"] == 'conditional_four_layer_perceptron':
                FloatTensor = torch.cuda.FloatTensor if is_cuda_enabled() else torch.FloatTensor
                LongTensor = torch.cuda.LongTensor if is_cuda_enabled() else torch.LongTensor
                labels = LongTensor(np.random.randint(0, num_classes, n_samples))  # random labels between 0 and 9, output of shape batch_size

                labels = labels.view(-1, 1)
                labels_onehot = torch.FloatTensor(n_samples, num_classes)
                labels_onehot.zero_()
                labels_onehot.scatter_(1, labels, 1)

                input_labels = to_pytorch_variable(labels_onehot.type(FloatTensor))

                self.z = torch.cat((input_labels, z), -1)
            else:
                self.z = z

        else:
            self.z = z

        #HACK: If it's a sequential model, add another dimension to the noise input
        # Also we're currently just using a fixed sequence length for sequence generation; make this
        # able to be specified by the user.
        if self.individuals[0].genome.name in ["DiscriminatorSequential", "GeneratorSequential"]:
            sequence_length = 100
            self.z = self.z.unsqueeze(1).repeat(1,sequence_length,1)
コード例 #8
0
    def compute_loss_against(self, opponent, input, labels = None, alpha = None, beta = None, iter = None, log_class_distribution = False,):

        # need to pass in the labels from dataloader too in lipizzaner_gan_trainer.py
        # Compute loss using real images
        # Second term of the loss is always zero since real_labels == 1
        batch_size = input.size(0)

        FloatTensor = torch.cuda.FloatTensor if is_cuda_enabled() else torch.FloatTensor
        LongTensor = torch.cuda.LongTensor if is_cuda_enabled() else torch.LongTensor

        real_labels = torch.Tensor(batch_size)
        real_labels.fill_(0.9)
        real_labels = to_pytorch_variable(real_labels)

        fake_labels = to_pytorch_variable(torch.zeros(batch_size))

        labels = labels.view(-1, 1).cuda() if is_cuda_enabled() else labels.view(-1, 1)
        labels_onehot = torch.FloatTensor(batch_size, self.num_classes)
        labels_onehot.zero_()
        labels_onehot.scatter_(1, labels, 1)

        labels = to_pytorch_variable(labels_onehot.type(FloatTensor))

        instance_noise_std_dev_min = 0.5
        instance_noise_std_dev_max = 5.0
        instance_noise_std_dev = 2.5
        instance_noise_mean = 0


        # Adding instance noise to prevent Discriminator from getting too strong
        if iter is not None:
            std = max(
                instance_noise_std_dev_min,
                instance_noise_std_dev_max - iter * 0.001,
            )
        else:
            instance_noise_std_dev

        input_perturbation = to_pytorch_variable(
            torch.empty(input.shape).normal_(mean=instance_noise_mean, std=std)
        )

        input = input + input_perturbation

        dis_input = torch.cat((input, labels), -1)  # discriminator training data input

        outputs = self.net(dis_input).view(-1)  # pass in training data input and respective labels to discriminator
        d_loss_real = self.loss_function(outputs, real_labels)  # get real image loss of discriminator (output vs. 1)

        # torch.cat((img.view(img.size(0), -1), self.label_embedding(gen_labels)), -1)

        # Compute loss using fake images
        # First term of the loss is always zero since fake_labels == 0
        gen_labels = LongTensor(np.random.randint(0, self.num_classes, batch_size))  # random labels for generator input

        z = noise(batch_size, self.data_size)  # noise for generator input

        gen_labels = gen_labels.view(-1, 1)
        labels_onehot = torch.FloatTensor(batch_size, self.num_classes)
        labels_onehot.zero_()
        labels_onehot.scatter_(1, gen_labels, 1)

        gen_labels = to_pytorch_variable(labels_onehot.type(FloatTensor))

        gen_input = torch.cat((gen_labels, z), -1)

        fake_images = opponent.net(gen_input)
        # print('fake images shape')
        # print(fake_images.shape)
        dis_input = torch.cat((fake_images, gen_labels), -1)  # discriminator training data input
        outputs = self.net(dis_input).view(-1)
        d_loss_fake = self.loss_function(outputs, fake_labels)  # get fake image loss of discriminator (output vs. 0)

        return (d_loss_real + d_loss_fake), None