Beispiel #1
0
    def predict(self, X, condition_data=None):
        use_condition = _check_conditions(self.conditions, condition_data)
        self.eval()  # Deactivate dropout
        if self.conditions:
            self.conditions.eval()
        pred = []

        with torch.no_grad():
            for start in range(0, X.shape[0], self.batch_size):
                # batched predictions, yet inclusive
                end = start + self.batch_size
                X_batch = X[start:end].toarray()
                X_batch = torch.FloatTensor(X_batch)
                if torch.cuda.is_available():
                    X_batch = X_batch.cuda()
                X_batch = Variable(X_batch)

                if use_condition:
                    c_batch = [c[start:end] for c in condition_data]

                z = self.enc(X_batch)
                if use_condition:
                    z = self.conditions.encode_impose(z, c_batch)
                # reconstruct
                X_reconstuction = self.dec(z)
                # shift
                X_reconstuction = X_reconstuction.data.cpu().numpy()
                pred.append(X_reconstuction)
        return np.vstack(pred)
Beispiel #2
0
    def fit(self, X, y=None, condition_data=None):
        if y is not None:
            raise NotImplementedError("(Semi-)supervised usage not supported")

        use_condition = _check_conditions(self.conditions, condition_data)

        if use_condition:
            code_size = self.n_code + self.conditions.size_increment()
        else:
            code_size = self.n_code

        self.enc = Encoder(X.shape[1],
                           self.n_hidden,
                           self.n_code,
                           final_activation='linear',
                           normalize_inputs=self.normalize_inputs,
                           dropout=self.dropout,
                           activation=self.activation)
        self.dec = Decoder(code_size,
                           self.n_hidden,
                           X.shape[1],
                           dropout=self.dropout,
                           activation=self.activation)

        if torch.cuda.is_available():
            self.enc = self.enc.cuda()
            self.dec = self.dec.cuda()
        optimizer_gen = TORCH_OPTIMIZERS[self.optimizer]
        # Reconstruction
        self.enc_optim = optimizer_gen(self.enc.parameters(), lr=self.lr)
        self.dec_optim = optimizer_gen(self.dec.parameters(), lr=self.lr)

        # do the actual training
        for epoch in range(self.n_epochs):
            if self.verbose:
                print("Epoch", epoch + 1)

            # Shuffle on each new epoch
            if use_condition:
                # shuffle(*arrays) takes several arrays and shuffles them so indices are still matching
                X_shuf, *condition_data_shuf = sklearn.utils.shuffle(
                    X, *condition_data)
            else:
                X_shuf = sklearn.utils.shuffle(X)

            for start in range(0, X.shape[0], self.batch_size):
                end = start + self.batch_size
                X_batch = X_shuf[start:end].toarray()
                # condition may be None
                if use_condition:
                    # c_batch = condition_shuf[start:(start+self.batch_size)]
                    c_batch = [c[start:end] for c in condition_data_shuf]
                    self.partial_fit(X_batch, condition_data=c_batch)
                else:
                    self.partial_fit(X_batch)

            if self.verbose:
                # Clean up after flushing batch loss printings
                print()
        return self
Beispiel #3
0
    def partial_fit(self, X, y=None, condition_data=None):
        """ Performs reconstrction, discimination, generator training steps """
        _check_conditions(self.conditions, condition_data)

        if y is not None:
            raise ValueError("(Semi-)supervised usage not supported")
        # Transform to Torch (Cuda) Variable, shift batch to GPU
        X = Variable(torch.FloatTensor(X))
        if torch.cuda.is_available():
            X = X.cuda()

        # Make sure we are in training mode and zero leftover gradients
        self.train()
        # One step each, could balance
        recon_loss = self.ae_step(X, condition_data=condition_data)
        if self.verbose:
            log_losses(recon_loss, 0, 0)
        return self
Beispiel #4
0
 def forward(self, x, condition_data=None):
     if self.normalize_inputs:
         x = F.normalize(x, 1)
     # TODO could I use x instead of self.inp? Do we need x.view?
     mu, logvar = self.encode(x.view(-1, self.inp))
     z = self.reparametrize(mu, logvar)
     use_condition = _check_conditions(self.conditions, condition_data)
     if use_condition:
         z = self.conditions.encode_impose(z, condition_data)
     return self.decode(z), mu, logvar
Beispiel #5
0
    def fit(self, X, y=None, condition_data=None):
        """
        :param X: np.array, the base data from Bag class
        :param y: dummy variable, throws Error if used
        :param condition_data: generic list of conditions
        :return:
        """
        ### DONE Adapt to generic condition ###
        # TODO: check how X representation and numpy.array work together
        # TODO: adapt combining X and new_conditions_name
        if y is not None:
            raise NotImplementedError("(Semi-)supervised usage not supported")

        use_condition = _check_conditions(self.conditions, condition_data)

        # do the actual training
        for epoch in range(self.n_epochs):
            if self.verbose:
                print("Epoch", epoch + 1)

            if use_condition:
                # shuffle(*arrays) takes several arrays and shuffles them so indices are still matching
                X_shuf, *condition_data_shuf = sklearn.utils.shuffle(
                    X, *condition_data)
            else:
                X_shuf = sklearn.utils.shuffle(X)

            for start in range(0, X.shape[0], self.batch_size):
                end = start + self.batch_size
                X_batch = X_shuf[start:end]
                # condition may be None
                if use_condition:
                    # c_batch = condition_shuf[start:(start+self.batch_size)]
                    c_batch = [c[start:end] for c in condition_data_shuf]
                    self.partial_fit(X_batch, condition_data=c_batch)
                else:
                    self.partial_fit(X_batch)

            if self.verbose:
                # Clean up after flushing batch loss printings
                print()
        return self
Beispiel #6
0
    def predict(self, X, condition_data=None):
        """
        :param X: np.array, the base data from Bag class
        :param condition_data: generic list of conditions
        :return:
        """
        ### DONE Adapt to generic condition ###
        use_condition = _check_conditions(self.conditions, condition_data)

        self.eval()  # Deactivate dropout
        if self.conditions:
            self.conditions.eval()
        pred = []
        with torch.no_grad():
            test_loss = 0
            for start in range(0, X.shape[0], self.batch_size):
                # batched predictions, yet inclusive
                end = start + self.batch_size
                X_batch = X[start:end]
                if sp.issparse(X_batch):
                    X_batch = X_batch.toarray()
                # as_tensor does not make a copy of X_batch
                X_batch = torch.as_tensor(X_batch,
                                          dtype=torch.float32,
                                          device=self.device)

                if use_condition:
                    c_batch = [c[start:end] for c in condition_data]

                if use_condition:
                    recon_batch, mu, logvar = self(X_batch, c_batch)
                else:
                    recon_batch, mu, logvar = self(X_batch)
                test_loss += self.loss_function(recon_batch, X_batch, mu,
                                                logvar).item()
                pred.append(recon_batch.data.cpu().numpy())

            test_loss /= X.shape[0]
            print('====> Test set loss: {:.4f}'.format(test_loss))

        return np.vstack(pred)
Beispiel #7
0
    def ae_step(self, batch, condition_data=None):
        """ Perform one autoencoder training step """
        z_sample = self.enc(self.corrupt(batch, self.noise_factor))

        use_condition = _check_conditions(self.conditions, condition_data)
        if use_condition:
            z_sample = self.conditions.encode_impose(z_sample, condition_data)

        x_sample = self.dec(z_sample)
        recon_loss = F.binary_cross_entropy(
            x_sample + TINY,
            batch.view(batch.size(0), batch.size(1)) + TINY)
        self.enc_optim.zero_grad()
        self.dec_optim.zero_grad()
        if self.conditions:
            self.conditions.zero_grad()
        recon_loss.backward()
        self.enc_optim.step()
        self.dec_optim.step()
        if self.conditions:
            self.conditions.step()
        return recon_loss.item()
Beispiel #8
0
    def partial_fit(self, X, y=None, condition_data=None):
        """
            Performs reconstrction, discimination, generator training steps
        :param X: np.array, the base data from Bag class
        :param y: dummy variable, throws Error if used
        :param condition_data: generic list of conditions
        :return:
        """
        ### DONE Adapt to generic condition ###
        use_condition = _check_conditions(self.conditions, condition_data)

        if y is not None:
            raise ValueError("(Semi-)supervised usage not supported")

        # Transform to Torch (Cuda) Variable, shift batch to GPU
        if sp.issparse(X):
            X = X.toarray()
        X = torch.as_tensor(X, dtype=torch.float32, device=self.device)

        # Make sure we are in training mode and zero leftover gradients
        self.train()
        self.optimizer.zero_grad()
        # Build the model on the concatenated data, compute BCE without concatenation
        if use_condition:
            recon_batch, mu, logvar = self(X, condition_data)
        else:
            recon_batch, mu, logvar = self(X)

        loss = self.loss_function(recon_batch, X, mu, logvar)
        if use_condition:
            self.conditions.zero_grad()
        loss.backward()
        self.optimizer.step()
        if use_condition:
            self.conditions.step()
        if self.verbose:
            # Log batch loss
            log_losses(loss.item() / len(X))
        return self
Beispiel #9
0
    def predict(self, X, condition_data=None):
        use_condition = _check_conditions(self.conditions, condition_data)

        batch_size = 128
        test_users = list(X.keys())
        test_user_num = len(test_users)
        index = 0
        pred = []
        while True:
            if index >= test_user_num:
                break
            user_batch = test_users[index:index + batch_size]
            if use_condition:
                c_batch = [c[index:index + batch_size] for c in condition_data]
            index += batch_size

            user_batch_rating = self.generator.all_rating(user_batch, c_batch, impose_dim=1)

            user_batch_rating = user_batch_rating.detach_().cpu().numpy()
            for user_batch_rating_uid in zip(user_batch_rating, user_batch):
                pred.append(self.simple_test_one_user(user_batch_rating_uid))

        return pred
Beispiel #10
0
    def fit(self, X, y=None, condition_data=None):
        """
        :param X: np.array, the base data from Bag class
        :param y: dummy variable, throws Error if used
        :param condition_data: generic list of conditions
        :return:
        """

        if y is not None:
            raise NotImplementedError("(Semi-)supervised usage not supported")

        use_condition = _check_conditions(self.conditions, condition_data)

        self.user_pos_train = X

        # minimax training
        for epoch in range(self.n_epochs):
            if self.verbose:
                print("Epoch", epoch + 1)

            if epoch >= 0:
                for d_epoch in range(self.d_epochs): #100
                    if d_epoch % 5 == 0:
                        self.generate_for_d(DIS_TRAIN_FILE, condition_data)
                        train_size = ut.file_len(DIS_TRAIN_FILE)
                    index = 1
                    while True:
                        if index > train_size:
                            break
                        if index + self.batch_size <= train_size + 1:
                            input_user, input_item, input_label = ut.get_batch_data(DIS_TRAIN_FILE, index,
                                                                                    self.batch_size)
                        else:
                            input_user, input_item, input_label = ut.get_batch_data(DIS_TRAIN_FILE, index,
                                                                                    train_size - index + 1)

                        if torch.cuda.is_available():
                            input_label = torch.tensor(input_label).cuda()
                        else:
                            input_label = torch.tensor(input_label)
                        if use_condition:
                            # Each user is repeated a varying number of times in dis_train.txt, users not ordered
                            user_cnt = collections.OrderedDict([(u, input_user.count(u)) for u in set(input_user)])
                            c_batch = []
                            for c in condition_data:
                                raw_c_batch = []
                                for u in set(input_user):
                                    raw_c_batch.append(c[u])
                                c_batch.append(np.asarray(raw_c_batch).repeat(list(user_cnt.values()), axis=0))
                            D_loss = self.discriminator(input_user, input_item, input_label, c_batch)
                        else:
                            D_loss = self.discriminator(input_user, input_item, input_label)
                        self.discriminator.step(D_loss)
                        index += self.batch_size

                    if self.verbose:
                        print("\r[D Epoch %d/%d] [loss: %f]" % (d_epoch, self.d_epochs, D_loss.item()))

                # Train G
                for g_epoch in range(self.g_epochs):  # 50
                    for u in self.user_pos_train:
                        sample_lambda = 0.2
                        pos = self.user_pos_train[u]

                        if use_condition:
                            c_batch = [c[u] for c in condition_data]
                            rating = self.generator.all_logits(u, c_batch)
                        else:
                            rating = self.generator.all_logits(u)
                        rating = rating.detach_().cpu().numpy()
                        exp_rating = np.exp(rating)
                        prob = exp_rating / np.sum(exp_rating)  # prob is generator distribution p_\theta

                        pn = (1 - sample_lambda) * prob
                        pn[pos] += sample_lambda * 1.0 / len(pos)
                        # Now, pn is the Pn in importance sampling, prob is generator distribution p_\theta

                        # print('pn sum=',pn.sum())
                        # Normilize by probability sum to avoid np.random.choice error 'probability do not sum to one'
                        pn /= pn.sum()
                        sample = np.random.choice(np.arange(self.item_num), 2 * len(pos), p=pn)
                        ###########################################################################
                        # Get reward and adapt it with importance sampling
                        ###########################################################################
                        reward = self.discriminator.get_reward(u, sample)
                        reward = reward.detach_().cpu().numpy() * prob[sample] / pn[sample]
                        ###########################################################################
                        # Update G
                        ###########################################################################
                        if torch.cuda.is_available():
                            sample = torch.tensor(sample).cuda()
                            reward = torch.tensor(reward).cuda()
                        else:
                            sample = torch.tensor(sample)
                            reward = torch.tensor(reward)
                        if use_condition:
                            c_batch = [c[u] for c in condition_data]
                            G_loss = self.generator(u, sample, reward, c_batch)
                        else:
                            G_loss = self.generator(u, sample, reward)
                        self.generator.step(G_loss)

                    if self.verbose:
                        print("\r[G Epoch %d/%d] [loss: %f]" % (g_epoch, self.g_epochs, G_loss.item()))

        return self