元素明智的计算打破了自动分级

时间:2019-02-06 03:03:32

标签: python-3.x machine-learning pytorch logistic-regression

我正在使用pytorch来计算逻辑回归的损失(我知道pytorch可以自动执行此操作,但我必须自己做)。我的函数在下面定义,但是对torch.tensor的强制转换会破坏autograd并给我w.grad = None。我是pytorch的新手,所以我很抱歉。

logistic_loss = lambda X,y,w: torch.tensor([torch.log(1 + torch.exp(-y[i] * torch.matmul(w, X[i,:]))) for i in range(X.shape[0])], requires_grad=True)

1 个答案:

答案 0 :(得分:2)

您的帖子在细节上不太清楚,这是单线的怪物。我首先对其进行了重新设计以制作一个minimal, complete, verifiable示例。如果我误解了您的意图,请指正我,下次再做。

import torch

# unroll the one-liner to have an easier time understanding what's going on
def logistic_loss(X, y, w):
    elementwise = []
    for i in range(X.shape[0]):
        mm = torch.matmul(w, X[i, :])
        exp = torch.exp(-y[i] * mm)
        elementwise.append(torch.log(1 + exp))

    return torch.tensor(elementwise, requires_grad=True)

# I assume that's the excepted dimensions of your input
X = torch.randn(5, 30, requires_grad=True)
y = torch.randn(5)
w = torch.randn(30)

# I assume you backpropagate from a reduced version
# of your sum, because you can't call .backward on multi-dimensional
# tensors
loss = logistic_loss(X, y, w).mean()
loss.mean().backward()
print(X.grad)

最简单的解决方案是将torch.tensor(elementwise, requires_grad=True)替换为torch.stack(elementwise)。您可以将torch.tensor视为全新张量的构造器,如果张量更多是某种数学表达式的结果,则应使用torch.stacktorch.cat之类的操作。

话虽如此,由于您在i上进行了手动循环,因此该代码仍然效率很低。相反,您可以简单地编写

def logistic_loss_vectorized(X, y, w):
    mm = torch.matmul(X, w)
    exp = torch.exp(-y * mm)

    return torch.log(1 + exp)

在数学上是等效的,但实际上会更快 ,因为由于缺少显式循环,它可以实现更好的并行化。

请注意,此代码仍然存在数值问题-您采用指数的对数,但是中间结果exp可能会达到很高的值,从而导致精度损失。有一些解决方法,这就是为什么PyTorch提供的损失函数更可取的原因。