我正在尝试从PyTorch中实现RankNet(学习排名)算法: https://www.microsoft.com/en-us/research/publication/from-ranknet-to-lambdarank-to-lambdamart-an-overview/
我已经实现了带有RELU激活的2层神经网络(MLP)。我正在使用权重衰减为0.01的Adam优化器。 如本文所述,我已经编写了一个自定义损失函数。详细信息如下:损失/成本等式: Loss_Image.png
在哪里, 对于给定的查询S_ij∈{0,±1}和 如果文件i被标记为比文件j更相关,则S_ij = 1, -1如果文档i被标记为与文档j的相关性较低, 和0(如果它们具有相同的标签)。 s_i和s_j是模型对查询URLs URL_i和URL_j的预测分数。
我还实现了NDCG功能,作为学习排名算法的评估指标。 我正在使用具有52k训练样本的LETOR MQ2008数据集。
损失功能
def custom_loss_func(x_tr, y_tr):
#x_tr = predicted score by the model
#y_tr = true score
loss_mean = torch.tensor(0.0)
x_tr = torch.squeeze(x_tr)
for i in range(len(x_tr))[::2]:
s_i = x_tr[i]
s_j = x_tr[i+1]
s_ij_diff = s_i - s_j
true_i = y_tr[i]
true_j = y_tr[i+1]
if true_i > true_j:
S_ij = 1
elif true_i < true_j:
S_ij = -1
else:
S_ij = 0
loss = (1 - S_ij) * s_ij_diff / 2. + torch.log(1 + torch.exp(-s_ij_diff))
loss_mean += loss
loss_mean /= (len(x_tr)/2)
return loss_mean
评估指标:NDCG
def calc_ndcg(y_true, y_pred, k):
y_pred = torch.squeeze(y_pred, 1)
dcg = torch.tensor([0.])
ideal_dcg = torch.tensor([0.])
y_true_sorted, index_y_true = torch.sort(y_true, descending=True)
y_pred_sorted, index_y_pred = torch.sort(y_pred, descending=True)
for i in range(k):
ideal_dcg += (torch.tensor(2.) ** y_true_sorted[i] - torch.tensor(1.)) / torch.log2(torch.tensor(i) + torch.tensor(2.))
for i in range(k):
dcg += (torch.tensor(2.) ** y_true[index_y_pred[i]] - torch.tensor(1.)) / torch.log2(torch.tensor(i) + torch.tensor(2.))
ndcg = dcg / ideal_dcg
return ndcg
主要
for epoch in range(epochs):
#model.train()
running_loss = 0.0
for i, each_batch in enumerate(pairs_dl, start=0):
xb, yb = get_train_batch(each_batch)
pred = model(xb)
loss = custom_loss_func(pred, yb)
running_loss += loss
opt.zero_grad()
loss.backward()
opt.step()
avg_loss = running_loss / (i+1)
print('[%d, %5d] loss: %.10f' % (epoch + 1, i + 1, avg_loss))
running_loss = 0.0
#model.eval()
with torch.no_grad():
y_pred_t = model(X_train_t)
ndcg_epoch = calc_ndcg(y_train_t, y_pred_t, 10)
这些是我的结果: Accuracy_Loss_image.png
从图中可以看出,训练精度(NDCG)波动很大,似乎是完全错误的。我还尝试了使用不同的超参数设置进行此操作,更改了学习速率,批处理大小,层数和神经元数量。
还尝试过验证集,它会导致丢失和NDCG错误。所以目前我主要关注的是首先要正确地掌握训练的准确性。
我猜在loss或NDCG函数中的某个地方出错了,或者在渐变中,但无法弄清楚。我的问题是我要去哪里错了,应该进行哪些更改以确保正确的准确性?
我是PyTorch的新手,对此我将非常感谢。预先感谢。