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
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
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
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
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
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
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
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
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:, :]