为自定义损失函数实现反向传播

Implementing Backprop for custom loss functions

我有一个具有矢量输出的神经网络 Network。我不想使用典型的损失函数,而是想实现自己的损失函数,它是某些 class 中的一种方法。这看起来像:

class whatever:
    def __init__(self, network, optimizer): 
         self.network = network
         self.optimizer = optimizer
    
    def cost_function(relevant_data):
        ...implementation of cost function with respect to output of network and relevant_data...

    def train(self, epochs, other_params):
        ...part I'm having trouble with...

我主要关心的是渐变。由于我采用了自己的自定义损失函数,是否需要针对成本函数实现自己的梯度?

一旦我做了数学计算,我意识到如果成本是 J,那么就网络最后一层的梯度而言,J 的梯度是一个相当简单的函数。即,它看起来像:Equation link.

如果我使用像 CrossEntropy 这样的传统损失函数,我的后台处理看起来像:

objective = nn.CrossEntropyLoss()
for epochs:
    optimizer.zero_grad()
    output = Network(input)
    loss = objective(output, data)
    loss.backward()
    optimizer.step()

但是在我的情况下我们如何做到这一点?我的猜测是这样的:

for epochs:
     optimizer.zero_grad()
     output = Network(input)
     loss = cost_function(output, data)
     #And here is where the problem comes in
     loss.backward()
     optimizer.step()
     

loss.backward() 据我了解,采用损失函数相对于参数的梯度。但是我仍然可以在使用我自己的损失函数时调用它吗(大概程序不知道梯度方程是什么)。我是否还必须实施另一个 method/subroutine 才能找到梯度?

这引出了我的另一个问题:如果我想为我的损失函数实现梯度计算,我还需要神经网络参数的梯度。我如何获得那些?有那个功能吗?

只要你从输入开始到损失函数的所有步骤都涉及对 PyTorch 的张量的可微操作,你就不需要做任何额外的事情。 PyTorch 构建了一个计算图来跟踪每个操作、它的输入和梯度。因此,对您的自定义损失调用 loss.backward() 仍会通过图表正确传播梯度。 A Gentle Introduction to torch.autograd 来自 PyTorch 教程可能是有用的参考。

反向传递后,如果需要直接访问梯度以进行进一步处理,可以使用 .grad 属性(因此 t.grad for tensor t in the图)。

最后,如果您有一个特定的用例来查找使用 PyTorch 的张量实现的任意可微函数相对于其输入之一的梯度(例如,损失相对于网络中特定权重的梯度) , 你可以使用 torch.autograd.grad.