提问者:小点点

在PyTorch自定义损失函数变量输入上的属性错误


我做了一个自定义损失函数来计算多输出多标签问题的交叉熵(CE)。在类中,我想设置我输入的目标变量不需要梯度。我在前向函数中使用类之外的预定义函数(取自pytorch源代码)来做到这一点。

    def _assert_no_grad(variable):
        assert not variable.requires_grad

    def forward(self, predicted, target):
        """
        Computes cross entropy between targets and predictions.
        """
        # No gradient over target
        _assert_no_grad(target)

        # Define variables
        p = predicted.clamp(0.01, 0.99)
        t = target.float()

        #Compute cross entropy
        h1 = p.log()*t
        h2 = (1-t)*((1-p).log())
        ce = torch.add(h1, h2)
        ce_out = torch.mean(ce, 1)
        ce_out = torch.mean(ce_out, 0)

        # Save for backward step
        self.save_for_backward(ce_out)

此时,当我在批量for循环中运行代码时(见下文),我收到以下错误:

对象没有属性requires_grad

这似乎很简单,因为我们应该传递一个torch. autograd.Variable,但是我已经在这样做了,可以在下面的片段中看到。

for t in range(50):

    print('Epoch {}'.format(t))
    if t > 0:
        print('Loss ->', loss)

    for batch_idx, (x_batch, y_batch) in enumerate(train_loader):
        # Wrap in Variable
        x_in, target = Variable(x_batch), Variable(y_batch)

        predicted = model(x_in)

        # Compute and print loss
        loss = criterion(predicted, target)

        # Zero gradients, perform a backward pass, and update the weights.
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

补充一下,我的最终目标是生成一个类,它的行为类似于BCELoss,除了多个标签,而不仅仅是二进制。我觉得我已经搜索了整个PyTorch文档,主要是使用这个和一些论坛条目。http://pytorch.org/docs/master/notes/extending.html

所以呢


共1个答案

匿名用户

问题出在将t变量转换为张量的“target. flot()”行中。您可以直接使用target,而不会在CE计算中出现任何问题。

此外,我想你并不真正需要"self.save_for_backward(ce_out)",因为我想你正在定义nn. Module类,它将在内部处理向后传递。

相关问题