一,计算图与动态图机制的介绍
1.计算图:
- 计算图:用于描述运算的有向无环图。
- 非叶子节点的梯度在计算过后默认丢弃,如需保存使用【tensor.retain_grad()】来对梯度进行保存
2.动态图:
- 静态图与动态图的区别在于:运算操作与搭建图的操作是否同时进行。
二,pytorch的自动求导机制
1.自动反向求梯度:
-
torcn.autograd.backward()
- tensors:用于求导的张量,一般为loss
- retain_graph:保存计算图,一般用于对计算图再次求导时需要用到
- create_graph:创建导数计算图,需要高阶求导时需要设置
- grad_tensors:多梯度权重,一般要设置某一个参数权重较大时需要设置
2.求取当前梯度
-
torch.autograd.grad()
- oututs:用于求导的张量,一般为loss
- inputs:需要求取梯度的张量,这是我们一般想要的
- create_graph:同上
- retain_graph:同上
- grad_outputs:多梯度权重
3.自动求导机制的特点
-
梯度不自动清零,需要手动【w.grad.zero_()】
-
依赖于叶子结点的结点,requires_grad默认为True
-
叶子结点不可执行in_place操作:因为记录了计算图中数据的地址,如果执行了inplace操作那么反向传播的时候就找不到原来的梯度值了就会对结果造成影响。
-
所有参数的测试代码如下,读者自行调试查看。
import torch
torch.manual_seed(10)
# ====================================== retain_graph ==============================================
# flag = True
flag = False
if flag:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
y.backward(retain_graph=True)#保存计算图,可以再次反向传播
print(w.grad)
y.backward()
# ====================================== grad_tensors ==============================================
# flag = True
flag = False
if flag:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x) # retain_grad()
b = torch.add(w, 1)
y0 = torch.mul(a, b) # y0 = (x+w) * (w+1)
y1 = torch.add(a, b) # y1 = (x+w) + (w+1) dy1/dw = 2.数据增强方法
loss = torch.cat([y0, y1], dim=0) # [y0, y1]
grad_tensors = torch.tensor([1., 2.])
loss.backward(gradient=grad_tensors) # gradient 传入 torch.autograd.backward()中的grad_tensors
print(w.grad)
# ====================================== autograd.gard ==============================================
# flag = True
flag = False
if flag:
x = torch.tensor([3.], requires_grad=True)
y = torch.pow(x, 2) # y = x**2.数据增强方法
grad_1 = torch.autograd.grad(y, x, create_graph=True) # grad_1 = dy/dx = 2x = 2.数据增强方法 * 3 = 6
print(grad_1)
grad_2 = torch.autograd.grad(grad_1[0], x)#再次求导--二阶导数 # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2.数据增强方法
print(grad_2)
# ====================================== tips: 1 ==============================================
# flag = True
flag = False
if flag:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
for i in range(4):
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
y.backward()
print(w.grad)
w.grad.zero_()#手动梯度清零,下划线表示inplace--原地操作
# ====================================== tips: 2.数据增强方法 ==============================================
# flag = True
flag = False
if flag:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
print(a.requires_grad, b.requires_grad, y.requires_grad)
# ====================================== tips: 3 ==============================================
# flag = True
flag = False
if flag:
a = torch.ones((1, ))
print(id(a), a)
# a = a + torch.ones((1, )) #地址不一样--不是inplace操作
# print(id(a), a)
a += torch.ones((1, )) #地址一样--为inplace操作,相当于加下划线的操作
print(id(a), a)
# flag = True
flag = False
if flag:
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)
w.add_(1)
y.backward()