在PyTorch中,处理非标量张量的反向传播确实更为抽象和自动,它通过autograd
模块实现了自动微分机制。在实际操作中,你不必直接构建和操作雅可比矩阵,而是依靠框架的API自动追踪和计算梯度。下面以几个例子说明:
例子1:非标量输出的简单反向传播
import torch
# 创建一个需要梯度计算的张量
x = torch.randn(3, requires_grad=True)
y = 2 * x # 假设这是一个简单的线性变换,y 是非标量张量
# 计算损失,这里假设我们对 y 的每个元素分别计算损失
losses = y.pow(2) # 对 y 的每个元素求平方作为损失函数
loss_sum = losses.sum() # 把所有损失加起来形成一个标量损失
# 对标量损失进行反向传播
loss_sum.backward()
# 输出 x 的梯度,这里虽然是非标量张量,但由于我们对所有元素的损失求和,
# 所以反向传播时得到的梯度是对所有元素的梯度之和,因此仍然是一个与 x 形状相同的张量
print(x.grad) # 输出:tensor([2., 2., 2.])
# 注意:如果不想对所有元素求和,而是对每个元素分别进行反向传播,需要指定 grad_tensors
# losses.backward(torch.ones_like(losses)) # 这里每个元素的梯度均为 2
例子2:非标量输出和指定梯度
在某些情况下,你可能希望对非标量损失函数的每个元素独立进行反向传播,这时可以传递一个与损失张量形状相同的梯度张量到 .backward()
方法中:
import torch
# 同样创建一个需要梯度计算的张量
x = torch.randn(3, requires_grad=True)
y = 2 * x
# 对 y 的每个元素分别计算损失,并保留原始损失张量
losses = y.pow(2)
# 对每个损失元素独立进行反向传播,这里传递一个与 losses 形状相同的张量作为梯度
custom_gradients = torch.ones_like(losses) # 假设我们对每个元素使用相同的自定义梯度
losses.backward(custom_gradients)
# 输出 x 的梯度,每个元素的梯度由 custom_gradients 决定
print(x.grad) # 输出:tensor([2., 2., 2.])