【进阶篇】全流程学习《20天掌握Pytorch实战》纪实 | Day06 | 自动微分机制
开源自由,知识无价~
@TOC
所用到的源代码及书籍+数据集以帮各位小伙伴下载放在文末,自取即可~
一、🎉前言
神经网络
通常依赖反向传播
求梯度
来更新网络参数
,求梯度过程通常是一件非常复杂而容易出错
的事情。
而==深度学习框架==可以帮助我们自动地完成这种求梯度运算。
Pytorch
一般通过反向传播 backward
方法 实现这种求梯度计算。该方法求得的梯度将存在对应自变量张量的grad
属性下。
除此之外,也能够调用torch.autograd.grad
函数来实现求梯度计算。
这就是Pytorch
的自动微分机制
。
简单来说就是,求梯度很麻烦,不过P有torch已经帮你解决了,下面就看看如何调用梯度求解吧~
之前写过一些关于求梯度的Blog,可以看一看哦~
二、🎉利用backward方法求导数
backward
方法通常在一个标量张量
上调用,该方法求得的梯度将存在对应自变量张量的grad
属性下。
如果调用的张量非标量,则要传入一个和它同形状 的gradient
参数张量。
相当于用该gradient
参数张量与调用张量作向量点乘
,得到的标量结果再反向传播
。
1. 标量的反向传播
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c的导数
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c
y.backward()
dy_dx = x.grad # 求梯度
print(dy_dx)
输出:
tensor(-2.)
2. 非标量的反向传播
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
print("x:\n",x)
print("y:\n",y)
y.backward(gradient = gradient)
x_grad = x.grad
print("x_grad:\n",x_grad)
输出:
x:
tensor([[0., 0.],
[1., 2.]], requires_grad=True)
y:
tensor([[1., 1.],
[0., 1.]], grad_fn=<AddBackward0>)
x_grad:
tensor([[-2., -2.],
[ 0., 2.]])
3. 非标量的反向传播可以用标量的反向传播实现
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
z = torch.sum(y*gradient)
print("x:",x)
print("y:",y)
z.backward()
x_grad = x.grad
print("x_grad:\n",x_grad)
输出:
x: tensor([[0., 0.],
[1., 2.]], requires_grad=True)
y: tensor([[1., 1.],
[0., 1.]], grad_fn=<AddBackward0>)
x_grad:
tensor([[-2., -2.],
[ 0., 2.]])
三、🎉利用autograd.grad方法求导数
autograd.grad
参数一共6个,分别是:outputs,inputs,gard_outputs,retain_graph,create_graph,allow_unused
。
outputs
:待被求导的tensor,作为第一个参数inputs
:被计算导数的叶子节点grad_outputs
:Jacobian-vector product中的向量retain_graph
:这是一个布尔型参数,如果为真的话,forward过程所创建的计算图将不会被销毁,如果为False,调用完该函数,forward过程的计算图将会被销毁,再次调用该函数需要重新建立计算图,默认值根create_graph的值相同create_graph
:这是一个布尔型参数,如果为真的话,这个梯度将会加入到计算图中,用来计算高阶导数或者其他计算,默认值为Falseallow_unused
:这也是一个布尔型参数,如果为True,则只返回inputs的梯度,而不返回其他叶子节点的,默认为Flase
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c的导数
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c
# create_graph 设置为 True 将允许创建更高阶的导数
dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
print(dy_dx.data)
# 求二阶导数
dy2_dx2 = torch.autograd.grad(dy_dx,x)[0]
print(dy2_dx2.data)
输出:
tensor(-2.)
tensor(2.)
==同时对多个自变量求导数==
import numpy as np
import torch
x1 = torch.tensor(1.0,requires_grad = True) # x需要被求导
x2 = torch.tensor(2.0,requires_grad = True)
y1 = x1*x2
y2 = x1+x2
# 允许同时对多个自变量求导数
(dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,inputs = [x1,x2],retain_graph = True)
print(dy1_dx1,dy1_dx2)
# 如果有多个因变量,相当于把多个因变量的梯度结果求和
(dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],inputs = [x1,x2])
print(dy12_dx1,dy12_dx2)
输出:
tensor(2.) tensor(1.)
tensor(3.) tensor(2.)
四、🎉利用自动微分和优化器求最小值
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c的最小值
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
optimizer = torch.optim.SGD(params=[x],lr = 0.01)
def f(x):
result = a*torch.pow(x,2) + b*x + c
return(result)
for i in range(500):
optimizer.zero_grad()
y = f(x)
y.backward()
optimizer.step()
print("y=",f(x).data,";","x=",x.data)
输出:
y= tensor(0.) ; x= tensor(1.0000)
🤗往期纪实
🥇总结
本期介绍了自动微分机制,主要从三个方法着手求解梯度,轮子已经造好,学会用就行了,还是比较简单的。
本文示例主要解释了张量数据结构的基本操作。对于0基础的同学来说可能还是稍有难度,因此,本文中给出了大部分使用到的库的解释,同时给出了部分代码的注释,以便小伙伴的理解,仅供参考,如有错误,请留言指出,最后一句:开源万岁~
同时为原作者打Call:
如果本书对你有所帮助,想鼓励一下作者,记得给本项目加一颗星星star⭐️,并分享给你的朋友们喔😊!
地址在这里哦:https://github.com/lyhue1991/eat_pytorch_in_20_days
😊Reference
书籍源码在此:
链接:https://pan.baidu.com/s/1P3WRVTYMpv1DUiK-y9FG3A
提取码:yyds
- 点赞
- 收藏
- 关注作者
评论(0)