hr, ndcg = self.validate(self.testloader, self.graph) cur_best = hr + ndcg > best_hr + best_ndcg if cur_best: best_hr, best_ndcg, best_epoch = hr, ndcg, self.epoch wait = 0 else: wait += 1 print('+ epoch {} tested, elapsed {:.2f}s, N@{}: {:.4f}, R@{}: {:.4f}'.format( self.epoch, time.time() - start_time, args.topk, ndcg, args.topk, hr ), flush=True)
时间: 2024-02-14 07:26:25 浏览: 56
这段代码是在每个训练轮次结束后进行模型验证的过程。
首先,调用 `self.validate()` 方法来评估当前训练模型在测试数据集上的性能。`self.testloader` 是测试数据集,`self.graph` 是用于评估的图形。
然后,计算当前的 `hr` 和 `ndcg` 与历史最佳值 `best_hr` 和 `best_ndcg` 的和,并将结果赋值给 `cur_best` 变量。
接下来,通过比较 `cur_best` 和 `True` 来确定当前性能是否超过了历史最佳性能。如果是,则更新 `best_hr`、`best_ndcg` 和 `best_epoch` 的值,并将等待计数器 `wait` 重置为 0。否则,将 `wait` 加 1。
最后,打印出当前轮次的验证结果,包括轮次数 `self.epoch`、经过的时间 `time.time() - start_time`、评估指标的值 `ndcg` 和 `hr`。
这个过程用于监控模型在验证集上的性能,并根据性能的提升或下降来决定是否保存当前模型的状态。通过比较当前性能与历史最佳性能,可以选择保存效果更好的模型状态。
相关问题
def validate(self, dataloader, graph): self.model.eval() hrs, ndcgs = [], [] with torch.no_grad(): tqdm_dataloader = tqdm(dataloader) for iteration, batch in enumerate(tqdm_dataloader, start=1): user_idx, item_idx = batch rep, user_pool = self.model(graph) user = rep[user_idx] + user_pool[user_idx] item = rep[self.model.n_user + item_idx] preds = self.model.predict(user, item) preds_hrs, preds_ndcgs = self.calc_hr_and_ndcg(preds, self.args.topk) hrs += preds_hrs ndcgs += preds_ndcgs return np.mean(hrs), np.mean(ndcgs)
这是一个 `validate` 方法的定义,它接受两个参数 `dataloader` 和 `graph`。这个方法用于在模型训练过程中对验证集进行评估。
首先,将模型设置为评估模式,即 `self.model.eval()`。
然后,定义了两个空列表 `hrs` 和 `ndcgs`,用于存储每个样本的评估结果。
接下来,通过一个循环遍历 `dataloader`,每次迭代时从 `dataloader` 中获取一个批次的数据,其中 `user_idx` 和 `item_idx` 是从批次中获取的用户索引和物品索引。
使用模型 `self.model` 和图数据 `graph` 调用 `self.model` 的方法,得到用户和物品的表示,并计算预测结果 `preds`。
再调用 `self.calc_hr_and_ndcg()` 方法,根据预测结果和 `self.args.topk` 计算命中率和NDCG(归一化折损累计增益)。
将计算得到的命中率和NDCG分别添加到 `hrs` 和 `ndcgs` 列表中。
最后,在循环结束后,计算 `hrs` 和 `ndcgs` 的平均值,并返回这两个平均值作为评估结果。
注意,在整个验证过程中,没有进行模型参数更新,因此使用了 `torch.no_grad()` 上下文管理器来禁用梯度计算,以提高效率。
def test(self): load_model(self.model, args.checkpoint) self.model.eval() with torch.no_grad(): rep, user_pool = self.model(self.graph) """ Save embeddings """ user_emb = (rep[:self.model.n_user] + user_pool).cpu().numpy() item_emb = rep[self.model.n_user: self.model.n_user + self.model.n_item].cpu().numpy() with open(f'HGMN-{self.args.dataset}-embeds.pkl', 'wb') as f: pickle.dump({'user_embed': user_emb, 'item_embed': item_emb}, f) """ Save results """ tqdm_dataloader = tqdm(self.testloader) uids, hrs, ndcgs = [], [], [] for iteration, batch in enumerate(tqdm_dataloader, start=1): user_idx, item_idx = batch user = rep[user_idx] + user_pool[user_idx] item = rep[self.model.n_user + item_idx] preds = self.model.predict(user, item) preds_hrs, preds_ndcgs = self.calc_hr_and_ndcg(preds, self.args.topk) hrs += preds_hrs ndcgs += preds_ndcgs uids += user_idx[::101].tolist() with open(f'HGMN-{self.args.dataset}-test.pkl', 'wb') as f: pickle.dump({uid: (hr, ndcg) for uid, hr, ndcg in zip(uids, hrs, ndcgs)}, f)
这是一个 `test` 方法的定义,用于在模型训练过程结束后对测试数据进行评估。
首先,加载模型的权重参数,使用 `load_model(self.model, args.checkpoint)` 方法将参数加载到模型中,并将模型设置为评估模式,即 `self.model.eval()`。
然后,在 `with torch.no_grad()` 上下文管理器中进行以下操作:
1. 使用模型和图数据 `self.graph` 调用模型 `self.model`,得到用户和物品的表示 `rep` 和 `user_pool`。
2. 保存嵌入向量:将用户嵌入向量和物品嵌入向量转换为 NumPy 数组,并使用 pickle 序列化保存到文件中。
3. 保存评估结果:通过遍历测试数据集中的批次,计算并保存每个用户的命中率和 NDCG 值。同时,也保存了每个用户的索引信息。最终将这些结果使用 pickle 序列化保存到文件中。
需要注意的是,在测试过程中,也没有进行模型参数的更新,因此使用了 `torch.no_grad()` 上下文管理器来禁用梯度计算,以提高效率。
这个方法的目的是对模型在测试数据集上的性能进行评估,并保存嵌入向量和评估结果供进一步分析和使用。
阅读全文