你的帖子在细节上不是很清楚,这是一个单行的怪物。我首先将它重新制作成一个 最小,完整,可验证 例。如果我误解了你的意图,请纠正我,请你下次自己动手。
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.stack 要么 torch.cat 。
torch.tensor(elementwise, requires_grad=True)
torch.stack(elementwise)
torch.tensor
torch.stack
torch.cat
话虽这么说,这个代码仍然非常低效,因为你手动循环 i 。相反,你可以简单地写
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提供的损失函数更可取的原因。
exp