示例#1
0
    def recommend(self, data, top_k, return_preds=False, allow_repeat=False):
        # Set model to eval mode
        model = self.net.to(self.device)
        model.eval()

        n_rows = data.shape[0]
        idx_list = np.arange(n_rows)
        recommendations = np.empty([n_rows, top_k], dtype=np.int64)
        all_preds = list()
        with torch.no_grad():
            for batch_idx in minibatch(
                    idx_list, batch_size=self.args.valid_batch_size):
                cur_batch_size = batch_idx.shape[0]
                batch_data = data[batch_idx].toarray()

                batch_users = np.expand_dims(batch_idx, 1)
                batch_users = torch.LongTensor(batch_users).to(self.device)

                all_items = np.arange(self.n_items)[None, :]
                all_items = np.tile(all_items, (cur_batch_size, 1))
                all_items = torch.LongTensor(all_items).to(self.device)

                preds = model(user_ids=batch_users, item_ids=all_items)
                if return_preds:
                    all_preds.append(preds)
                if not allow_repeat:
                    preds[batch_data.nonzero()] = -np.inf
                if top_k > 0:
                    _, recs = preds.topk(k=top_k, dim=1)
                    recommendations[batch_idx] = recs.cpu().numpy()

        if return_preds:
            return recommendations, torch.cat(all_preds, dim=0).cpu()
        else:
            return recommendations
示例#2
0
    def train_epoch(self, data):
        # Transpose the data first for ItemVAE.
        data = data.transpose()

        n_rows = data.shape[0]
        n_cols = data.shape[1]
        idx_list = np.arange(n_rows)

        # Set model to training mode.
        model = self.net.to(self.device)
        model.train()
        np.random.shuffle(idx_list)

        epoch_loss = 0.0
        batch_size = (self.args.batch_size
                      if self.args.batch_size > 0 else len(idx_list))
        for batch_idx in minibatch(idx_list, batch_size=batch_size):
            batch_tensor = sparse2tensor(data[batch_idx]).to(self.device)

            # Compute loss
            outputs = model(batch_tensor)
            loss = model.loss(data=batch_tensor, outputs=outputs).sum()
            epoch_loss += loss.item()

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

        return epoch_loss
示例#3
0
    def recommend(self, data, top_k, return_preds=False, allow_repeat=False):
        # Set model to eval mode
        model = self.net.to(self.device)
        model.eval()

        n_rows = data.shape[0]
        idx_list = np.arange(n_rows)
        recommendations = np.empty([n_rows, top_k], dtype=np.int64)
        all_preds = list()
        with torch.no_grad():
            for batch_idx in minibatch(idx_list,
                                       batch_size=self.args.valid_batch_size):
                batch_data = data[batch_idx]
                batch_tensor = sparse2tensor(batch_data).to(self.device)

                preds = model(batch_tensor, batch_user=batch_idx, predict=True)
                if return_preds:
                    all_preds.append(preds)
                if not allow_repeat:
                    preds[batch_data.nonzero()] = -np.inf
                if top_k > 0:
                    _, recs = preds.topk(k=top_k, dim=1)
                    recommendations[batch_idx] = recs.cpu().numpy()

        if return_preds:
            return recommendations, torch.cat(all_preds, dim=0).cpu()
        else:
            return recommendations
示例#4
0
    def train_epoch(self, data):
        n_rows = data.shape[0]
        n_cols = data.shape[1]
        idx_list = np.arange(n_rows)

        # Set model to training mode.
        model = self.net.to(self.device)
        model.train()
        np.random.shuffle(idx_list)

        epoch_loss = 0.0
        counter = 0
        for batch_idx in minibatch(idx_list, batch_size=self.args.batch_size):
            batch_tensor = sparse2tensor(data[batch_idx]).to(self.device)

            # Compute loss
            outputs = model(batch_tensor, batch_user=batch_idx)
            loss = model.loss(data=batch_tensor, outputs=outputs).mean()
            epoch_loss += loss.item()

            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
            counter += 1

        return epoch_loss / counter
示例#5
0
    def recommend(self, data, top_k, return_preds=False, allow_repeat=False):
        model = self.net

        n_rows = data.shape[0]
        n_cols = data.shape[1]
        idx_list = np.arange(n_rows)

        nns_sims = torch.zeros([n_cols, n_cols])
        for item in range(n_cols):
            topk_sims, topk_nns = model(item_id=item)
            nns_sims[item].put_(topk_nns, topk_sims)

        recommendations = np.empty([n_rows, top_k], dtype=np.int64)
        all_preds = list()
        with torch.no_grad():
            for batch_idx in minibatch(idx_list,
                                       batch_size=self.args.valid_batch_size):
                batch_tensor = sparse2tensor(data[batch_idx])

                preds = torch.mm(batch_tensor, nns_sims)
                if return_preds:
                    all_preds.append(preds)
                if not allow_repeat:
                    preds[data[batch_idx].nonzero()] = -np.inf
                if top_k > 0:
                    _, recs = preds.topk(k=top_k, dim=1)
                    recommendations[batch_idx] = recs.cpu().numpy()

        if return_preds:
            return recommendations, torch.cat(all_preds, dim=0).cpu()
        else:
            return recommendations
示例#6
0
    def train_sgd(self, data):
        n_rows = data.shape[0]
        n_cols = data.shape[1]
        idx_list = np.arange(n_rows)

        # Set model to training mode.
        model = self.net.to(self.device)
        model.train()
        np.random.shuffle(idx_list)

        epoch_loss = 0.0
        batch_size = (self.args.batch_size
                      if self.args.batch_size > 0 else len(idx_list))
        for batch_idx in minibatch(idx_list, batch_size=batch_size):
            batch_tensor = sparse2tensor(data[batch_idx]).to(self.device)

            # Compute loss
            outputs = model(user_id=batch_idx)
            loss = mse_loss(data=batch_tensor,
                            logits=outputs,
                            weight=self.weight_alpha).sum()
            epoch_loss += loss.item()

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

        return epoch_loss
示例#7
0
    def recommend(self, data, top_k, return_preds=False, allow_repeat=False):
        # Set model to eval mode
        model = self.net.to(self.device)
        model.eval()

        # Transpose the data first for ItemVAE.
        data = data.transpose()

        n_rows = data.shape[0]
        n_cols = data.shape[1]

        idx_list = np.arange(n_rows)
        recommendations = np.empty([n_cols, top_k], dtype=np.int64)

        # Make predictions first, and then sort for top-k.
        all_preds = list()
        with torch.no_grad():
            for batch_idx in minibatch(idx_list,
                                       batch_size=self.args.valid_batch_size):
                data_tensor = sparse2tensor(data[batch_idx]).to(self.device)
                preds = model(data_tensor)
                all_preds.append(preds)

        all_preds = torch.cat(all_preds, dim=0).t()
        data = data.transpose()
        idx_list = np.arange(n_cols)
        for batch_idx in minibatch(idx_list,
                                   batch_size=self.args.valid_batch_size):
            batch_data = data[batch_idx].toarray()
            preds = all_preds[batch_idx]
            if not allow_repeat:
                preds[batch_data.nonzero()] = -np.inf
            if top_k > 0:
                _, recs = preds.topk(k=top_k, dim=1)
                recommendations[batch_idx] = recs.cpu().numpy()

        if return_preds:
            return recommendations, all_preds.cpu()
        else:
            return recommendations
示例#8
0
    def train_epoch(self, data):
        # Get training pairs and sample negatives.
        user_ids, pos_item_ids = (data > 0).nonzero()
        neg_item_ids = self._sample_negative(user_ids, pos_item_ids,
                                             self._n_negatives)
        user_ids = np.expand_dims(user_ids, 1)
        pos_item_ids = np.expand_dims(pos_item_ids, 1)
        combined_item_ids = np.concatenate([pos_item_ids, neg_item_ids], 1)

        idx_list = np.arange(user_ids.shape[0])

        # Set model to training mode.
        model = self.net.to(self.device)
        model.train()
        np.random.shuffle(idx_list)

        epoch_loss = 0.0
        counter = 0
        for batch_idx in minibatch(
                idx_list, batch_size=self.args.batch_size):
            batch_users = user_ids[batch_idx]
            batch_items = combined_item_ids[batch_idx]
            batch_users = torch.LongTensor(batch_users).to(self.device)
            batch_items = torch.LongTensor(batch_items).to(self.device)

            # Compute loss
            outputs = model(user_ids=batch_users, item_ids=batch_items)
            loss = model.loss(outputs=outputs,
                              user_ids=batch_users,
                              item_ids=batch_items)
            epoch_loss += loss.item()

            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
            counter += 1

        return epoch_loss / counter
示例#9
0
    def fit_adv(self, data_tensor, epoch_num, unroll_steps, n_fakes,
                target_items):
        import higher

        if not data_tensor.requires_grad:
            raise ValueError("To compute adversarial gradients, data_tensor "
                             "should have requires_grad=True.")

        self._initialize()

        data_tensor = data_tensor.to(self.device)
        target_tensor = torch.zeros_like(data_tensor)
        target_tensor[:, target_items] = 1.0
        data_tensor = data_tensor.t()

        n_rows = data_tensor.shape[0]
        n_cols = data_tensor.shape[1]
        idx_list = np.arange(n_rows)

        # Set model to training mode.
        model = self.net.to(self.device)
        optimizer = self.optimizer

        batch_size = (self.args.batch_size
                      if self.args.batch_size > 0 else len(idx_list))
        for i in range(1, epoch_num - unroll_steps + 1):
            t1 = time.time()
            np.random.shuffle(idx_list)
            model.train()
            epoch_loss = 0.0
            for batch_idx in minibatch(idx_list, batch_size=batch_size):
                batch_tensor = data_tensor[batch_idx]
                # Compute loss
                outputs = model(batch_tensor)
                loss = model.loss(data=batch_tensor, outputs=outputs).sum()
                epoch_loss += loss.item()
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

            print("Training [{:.1f} s], epoch: {}, loss: {:.4f}".format(
                time.time() - t1, i, epoch_loss))

        with higher.innerloop_ctx(model, optimizer) as (fmodel, diffopt):
            print("Switching to higher mode...")
            for i in range(epoch_num - unroll_steps + 1, epoch_num + 1):
                t1 = time.time()
                np.random.shuffle(idx_list)
                epoch_loss = 0.0
                fmodel.train()
                for batch_idx in minibatch(idx_list, batch_size=batch_size):
                    batch_tensor = data_tensor[batch_idx]
                    # Compute loss
                    outputs = fmodel(batch_tensor)
                    loss = fmodel.loss(data=batch_tensor,
                                       outputs=outputs).sum()
                    epoch_loss += loss.item()
                    diffopt.step(loss)

                print("Training (higher mode) [{:.1f} s],"
                      " epoch: {}, loss: {:.4f}".format(
                          time.time() - t1, i, epoch_loss))

            print("Finished surrogate model training,"
                  " {} copies of surrogate model params.".format(
                      len(fmodel._fast_params)))

            fmodel.eval()
            all_preds = list()
            for batch_idx in minibatch(np.arange(n_rows),
                                       batch_size=batch_size):
                all_preds += [fmodel(data_tensor[batch_idx])]
            predictions = torch.cat(all_preds, dim=0).t()

            # Compute adversarial (outer) loss.
            adv_loss = mult_ce_loss(logits=predictions[:-n_fakes, ],
                                    data=target_tensor[:-n_fakes, ]).sum()
            adv_grads = torch.autograd.grad(adv_loss, data_tensor)[0]
            # Copy fmodel's parameters to default trainer.net().
            model.load_state_dict(fmodel.state_dict())

        return adv_loss.item(), adv_grads.t()[-n_fakes:, :]