7. 自动求导 2022-09-16

一个前向传播网络框架

网络计算流程

y=f(w, x) = Wx
y'=f'(w, x)w' = X
神经网络的训练需要使用损失函数的梯度,torch提供了一个torch.autograd的自动求导机制。

创建一个网络,并获取梯度

import torch

x = torch.ones(5)  # input tensor
y = torch.zeros(3)  # expected output
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)

print(f"Gradient function for z = {z.grad_fn}")
print(f"Gradient function for loss = {loss.grad_fn}")

这里拆分了w和b,在一些网络的计算中,可以按W = [w, b],作为统一参数。

使用 grad() 计算梯度

对于一个网络默认只会对最后一层网络进行自动求导,即最后一层requires_grad=true
如需对全网络进行求导,需使用

loss.backward()
print(w.grad)
print(b.grad)

关闭梯度计算

在网络的应用(前向计算, 使用部分已训练网络)中,为了计算效率,可以关闭梯度的自动计算

z = torch.matmul(x, w)+b
print(z.requires_grad)

with torch.no_grad():
    z = torch.matmul(x, w)+b
print(z.requires_grad)

或者

z = torch.matmul(x, w)+b
z_det = z.detach()
print(z_det.requires_grad)

网络的正向,反向传播

在torch中网络表达为DAG(directed acyclic graph),这里考虑mini-batch的情况。
在前向计算中autograd 完成如下两件事:

  1. 根据单层网络计算tensor结果
  2. 维护网络梯度计算函数
    在反向传播中,调用.backward(),完成如下事情:
  3. 使用tensor的梯度函数 .grad_fn计算梯度
  4. 累计梯度结果到 .grad中
  5. 使用链式法则,计算每一层

Jacobin矩阵的计算

对于多维loss function, 在计算y=f(x),在backward中会自动计算Jacobian Product: v^T*J,其中v是对应的tensor。

image.png
inp = torch.eye(5, requires_grad=True)
out = (inp+1).pow(2)
out.backward(torch.ones_like(inp), retain_graph=True)
print(f"First call\n{inp.grad}")
out.backward(torch.ones_like(inp), retain_graph=True)
print(f"\nSecond call\n{inp.grad}")
inp.grad.zero_()
out.backward(torch.ones_like(inp), retain_graph=True)
print(f"\nCall after zeroing gradients\n{inp.grad}")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容