动态计算图框架,根据运行时定义计算,可以在迭代中修改计算图,最终对标量输出节点使用 .backward() 实现自动求导并将梯度累积保存在 .grad 里。比如,想要知道模型分类不够理想的地方表现在输入图像的哪些区域上,可以这样做:
# 一般张量要设置了梯度需求才会在后续 backward 中保存梯度
x = x.requires_grad_(True)
# 分类的模型和损失函数,在计算期间产生的张量如 y 和 loss 都会保存一个 grad_fn,指向用于计算当前层反向传播的 Function 对象
y = model.forward(x)
loss = target_loss(y)
# 执行 backward() 会沿着 grad_fn 逐步往前计算梯度
# 注意,如果没有设置 retain_grad() 的话会在 backward() 之后清空计算图的前向缓存,也就是这次涉及的相关节点都不能再进行反向传播了
loss.backward()
# 对梯度后处理,转换成 opencv 图像用来观察 loss 的产生原因对应到输入的区域
saliency_map = torch.sum(torch.abs(x.grad), axis=1, keepdims=True)
saliency_map = saliency_map.detach().cpu().numpy()
saliency_map = cvglue.scale_min_max(saliency_map, 0, 255, percentile=99)
saliency_map = np.uint8(saliency_map[0].transpose((1,2,0)))
2024/5/9大约 35 分钟
