【问题标题】:How to use backpropagation with a self-defined loss in pytorch?如何在pytorch中使用带有自定义损失的反向传播?
【发布时间】:2019-02-03 04:15:43
【问题描述】:

我正在尝试在两个图像之间实现排名损失的连体网络。如果我定义自己的损失,我可以按如下方式执行反向传播步骤吗?当我运行它时,有时在我看来它给出的结果与单个网络给出的结果相同。

with torch.set_grad_enabled(phase == 'train'):
    outputs1 = model(inputs1)
    outputs2 = model(inputs2)
    preds1 = outputs1;
    preds2 = outputs2;

    alpha = 0.02;
    w_r = torch.tensor(1).cuda(async=True);

    y_i, y_j, predy_i, predy_j = labels1,labels2,outputs1,outputs2;
    batchRankLoss =  torch.tensor([max(0,alpha - delta(y_i[i], y_j[i])*predy_i[i] - predy_j[i])) for i in range(batchSize)],dtype = torch.float)
    rankLossPrev = torch.mean(batchRankLoss)                                             
    rankLoss = Variable(rankLossPrev,requires_grad=True)

    loss1 = criterion(outputs1, labels1)
    loss2 = criterion(outputs2, labels2)


    #total loss = loss1 + loss2 + w_r*rankLoss
    totalLoss = torch.add(loss1,loss2)
    w_r = w_r.type(torch.LongTensor)
    rankLossPrev = rankLossPrev.type(torch.LongTensor)
    mult = torch.mul(w_r.type(torch.LongTensor),rankLossPrev).type(torch.FloatTensor)
    totalLoss = torch.add(totalLoss,mult.cuda(async = True));

     # backward + optimize only if in training phase
         if phase == 'train':
            totalLoss.backward()
            optimizer.step()

            running_loss += totalLoss.item() * inputs1.size(0)

【问题讨论】:

    标签: python machine-learning conv-neural-network pytorch backpropagation


    【解决方案1】:

    您有几行代码可以从构造函数或转换为另一种数据类型生成新的张量。执行此操作时,您断开了您希望 backwards() 命令区分的操作链。

    这个转换断开了图形,因为转换是不可微的:

    w_r = w_r.type(torch.LongTensor)
    

    从构造函数构建张量将断开图形:

    batchRankLoss = torch.tensor([max(0,alpha - delta(y_i[i], y_j[i])*predy_i[i] - predy_j[i])) for i in range(batchSize)],dtype = torch.float)
    

    从文档中,将张量包装在变量中会将 grad_fn 设置为 None(也断开图表):

    rankLoss = Variable(rankLossPrev,requires_grad=True)
    

    假设您的critereon 函数是可微的,那么梯度当前仅通过loss1loss2 向后流动。在调用type() 之前,您的其他渐变只会流到mult。这与您的观察一致,即您的自定义损失不会改变您的神经网络的输出。

    为了让梯度在您的自定义损失中反向流动,您必须编写相同的逻辑,同时避免 type() 强制转换并在不使用列表推导的情况下计算 rankLoss

    【讨论】:

      【解决方案2】:
         rank_loss = torch.mean([torch.max(0,alpha - delta(y_i[i], y_j[i])*predy_i[i] - predy_j[i])) for i in range(batchSize)], dim=0)
         w_r = 1.0
         loss1 = criterion(outputs1, labels1)
         loss2 = criterion(outputs2, labels2)
         total_loss = loss1 + loss2 + w_r  * rank_loss 
         if phase == 'train':
             total_loss .backward()
             optimizer.step()
      

      您不必一遍又一遍地创建张量。如果你对每个损失有不同的权重并且权重只是常数,你可以简单地写:

      total_loss = weight_1 * loss1 + weight_2 * loss2 + weight_3  * rank_loss
      

      无论如何,这是不可训练的常量,创建 A 变量并将 requires_grad 设置为 True 是没有意义的,因为权重只是常量。 请升级到 pytorch 0.4.1,您不必在其中使用变量包装所有内容

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-18
        • 2020-09-10
        • 2018-06-14
        • 2021-07-27
        • 2019-11-14
        • 1970-01-01
        • 2021-09-26
        • 2019-04-27
        相关资源
        最近更新 更多