在PyTorch中实施RankNet时获得准确性的误差/波动

时间:2019-02-26 16:17:18

标签: machine-learning neural-network deep-learning pytorch ranking

我正在尝试从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 MQ20​​08数据集。

  

损失功能

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

  • hidden1单元数= 64
  • hidden2层单位数= 32
  • 纪元数= 100
  • 批量大小= 32
  • 学习率= 1e-05
  • NDCG k = 10

从图中可以看出,训练精度(NDCG)波动很大,似乎是完全错误的。我还尝试了使用不同的超参数设置进行此操作,更改了学习速率,批处理大小,层数和神经元数量。 还尝试过验证集,它会导致丢失和NDCG错误。所以目前我主要关注的是首先要正确地掌握训练的准确性。
我猜在loss或NDCG函数中的某个地方出错了,或者在渐变中,但无法弄清楚。我的问题是我要去哪里错了,应该进行哪些更改以确保正确的准确性?

我是PyTorch的新手,对此我将非常感谢。预先感谢。

0 个答案:

没有答案