Получение ошибок / колебаний в точности при реализации RankNet в PyTorch - PullRequest
0 голосов
/ 26 февраля 2019

Я пытаюсь реализовать алгоритм RankNet (обучение рангу) в PyTorch из этой статьи: https://www.microsoft.com/en-us/research/publication/from-ranknet-to-lambdarank-to-lambdamart-an-overview/

Я реализовал двухслойную нейронную сеть (MLP) с активацией RELU.Я использую оптимизатор Адама, с уменьшением веса 0,01.Я написал пользовательскую функцию потерь, как упомянуто в статье.Подробности следующие:

Уравнение потерь / затрат: Loss_Image.png

где, для данного запроса S_ij ∈ {0, ±1} и S_ij = 1, если документ i помечен как более релевантный, чем документ j, -1, если документ i помечен как менее релевантный, чем документ j, и 0, если они имеют одинаковую метку.s_i и s_j - это прогнозируемые оценки по модели для URL-адресов URL_i и URL_j запроса.

Кроме того, я реализовал функцию NDCG в качестве метрики оценки алгоритма обучения рангу.Я использую набор данных LETOR MQ2008 с обучающими выборками 52 000.

Функция потерь

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

Main

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

  • Количество скрытых 1 единиц = 64
  • Количество скрытых 2 единиц слоя = 32
  • Количество эпох = 100
  • Размер партии = 32
  • Скорость обучения = 1e-05
  • NDCG k = 10

Как видно из рисунка, точность обучения (NDCG) сильно колеблется и кажется совершенно неверной.Я также попробовал это с различными настройками гиперпараметра, изменяя скорость обучения, размер пакета, количество слоев, количество нейронов.Также пробовал на проверочном наборе, и это дает ошибки как в потерях, так и в NDCG.Поэтому в настоящее время я сосредотачиваюсь на том, чтобы сначала получить правильную точность обучения.
Я предполагаю, что где-то в функции потерь или NDCG я делаю ошибку или в градиентах, но не в состоянии выяснить это.У меня вопрос, где я ошибаюсь, и какие изменения я должен внести, чтобы получить правильную точность?

Я новичок в PyTorch, и я был бы очень признателен за любую помощь в этом.Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...