自动求导
自动求导:计算一个函数在特定值的导数
计算图:
(1)将代码分解成操作子
(2)将计算表示成无环图
(3)显示构造
import mxnet
import sym
# MXNet是亚马逊(Amazon)选择的深度学习库
# 它嵌入在宿主语言中,将声明性符号表达式与命令式张量计算混合在一起。
# 它提供自动微分来推导梯度。
# sympy是一个Python的科学计算库,
# 用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运算等等计算问题。
# 显式构造:先写出方程,再带入数据
a=sym.var()
b=sym.var()
c=2*a+b
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[20], line 1
----> 1 import mxnet
2 import sym
3 # MXNet是亚马逊(Amazon)选择的深度学习库
4 # 它嵌入在宿主语言中,将声明性符号表达式与命令式张量计算混合在一起。
5 # 它提供自动微分来推导梯度。
6 # sympy是一个Python的科学计算库,
7 # 用一套强大的符号计算体系完成诸如多项式求值、求极限、解方程、求积分、微分方程、级数展开、矩阵运算等等计算问题。
8 # 显式构造:先写出方程,再带入数据
ModuleNotFoundError: No module named 'mxnet'
# 隐式构造
import mxnet
import autograd, nd # autograd:基于numpy的自动求导
with autograd.record():
a=nd,ones((2,1))
b=nd.ones((2,1))
c=2*a+b
# 让计算机记住计算过程
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[19], line 2
1 # 隐式构造
----> 2 import mxnet
3 import autograd, nd # autograd:基于numpy的自动求导
5 with autograd.record():
ModuleNotFoundError: No module named 'mxnet'
自动求导的两种模式:
链式法则
(1)正向累积:求复合函数的值
(2)反向累积:求偏导数和梯度
自动求导实现
求y=2 X^T*X
import torch
x=torch.arange(4.0) # 创建向量x
x
tensor([0., 1., 2., 3.])
计算y关于x的梯度之前,需要找一个地方来存储梯度
x.requires_grad_(True) # 等价于x=torch.arange(4.0, requires_grads=True)
x.grad # 存储y关于x的导数,默认值是None
计算y
y=2*torch.dot(x,x) # X^T*X: x和x的点内积
y
tensor(28., grad_fn=<MulBackward0>)
通过调用反向传播函数自动计算y关于x的每个分量的梯度
y.backward() # 调用反向传播函数求导
x.grad # 访问导数
tensor([ 0., 4., 8., 12.])
x.grad==4*x
tensor([True, True, True, True])
计算x的另一个函数
# 默认情况下,pytorch会累积梯度,需要清楚之前的值
x.grad.zero_() # zero_(): pytorch中,_表示重写内容,zero_()表示初始化,清零
y=x.sum() # sum函数其实是x1+x2+x3+...+xn,偏导数就是全1
y.backward()
x.grad
tensor([1., 1., 1., 1.])
深度学习中,目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。
若y不是标量:
对于非标量调用backward()需要传入一个gradient参数,
x.grad.zero_()
y=x*x # y非标量,也是向量
y.sum().backward() # 把向量y通过sum的形式转换成标量,在求导,等价于y.backward(torch.ones(len(x)))
x.grad
# 标量关于向量求导,得到是向量
# 向量关于向量求导,得到是矩阵
tensor([0., 2., 4., 6.])
将某些计算移动到记录的计算图之外
x.grad.zero_()
y=x*x
u=y.detach() # 将y作为常数,而不是关于x的函数,u=常数
z=u*x # z=常数*x
z.sum().backward()
x.grad==u # z关于x求导后,结果=u
tensor([True, True, True, True])
x.grad.zero_()
y=x*x
y.sum().backward()
x.grad==2*x
tensor([True, True, True, True])
当需要通过python计算控制流(条件、循环或任意函数调用),依然可以计算得到变量的梯度
def f(a):
b=a*2
while b.norm()<1000: # norm()是求欧几里得范数,即向量的长度(直角三角形345)
b=b*2
if b.sum()>0:
c=b
else:
c=100*b
return c
a=torch.randn(size=(),requires_grad=True)
# torch.randn()返回一个张量,包含了从标准正态分布(均值为0,方差为1,即高斯白噪声)中抽取的一组随机数。张量的形状由参数sizes定义。
d=f(a)
# 调用f(a)函数返回的值,是一个关于a的分段函数,所以d是关于a的导数就是这个线性函数中a的系数
d.backward()
a.grad==d/a
tensor(True)
补充:关于torch.randn(size)
当size是n个数时,m_1,m_2,…,m_n,若n为奇数,则返回一个m_1行1列的张量,其中每个元素是一个m_2行m_3列的张量,…,又其中每个元素是一个m_n-1行m_n列的张量,最小元素的每一行服从正态分布
当size是n个数时,m_1,m_2,…,m_n,若n为偶数,则返回一个m_1行m_2列的张量,其中每个元素是一个m_3行m_4列的张量,…,又其中每个元素是一个m_n-1行m_n列的张量,最小元素的每一行服从正态分布
————————————————
原文链接:https://blog.csdn.net/zwma_33/article/details/115132177
size是1个数:长度为4的正态分布张量
import torch
torch.randn(4)
tensor([0.1624, 0.6806, 1.0137, 1.0331])
torch.randn(2,3)
tensor([[ 0.8812, -0.1866, 1.2854],
[ 2.2822, 1.3769, -0.6210]])
torch.randn(2,3,4)
tensor([[[ 0.1948, 0.2902, 1.6829, -1.3023],
[-0.5463, 0.3991, -1.9238, 1.1762],
[-1.4905, 0.8645, 0.4312, 1.5410]],
[[-0.7439, -0.0426, 0.5510, -0.4617],
[-0.6498, -0.1340, -1.1558, 1.5041],
[ 0.4622, -0.1978, 0.4462, -2.4797]]])
torch.randn(2,3,4,5)
tensor([[[[ 1.3482, -0.4547, 1.0909, -0.0041, -0.4880],
[-0.8528, -0.8525, 0.1817, 1.3697, 1.0281],
[ 0.8929, 0.4748, 0.9333, 0.1865, -1.3947],
[ 0.3428, -0.2172, 0.3989, -0.2984, -0.7311]],
[[-0.0032, 2.1011, -0.5717, 0.6919, -2.2922],
[-0.2949, -0.4430, -0.7788, -0.5935, 0.4042],
[-0.1868, 0.2241, -0.4737, 0.3487, -0.4286],
[-0.9932, -0.5781, -0.3121, 0.0037, -0.5333]],
[[ 0.0825, 0.4226, 0.7720, 1.6736, -1.3302],
[ 0.4627, -0.8111, -1.7965, -0.7345, 2.5270],
[ 0.3212, 1.6159, -0.1010, -0.6063, -0.9151],
[ 0.5598, -0.3219, -0.1356, -1.7648, -0.4553]]],
[[[ 0.6027, -0.9403, 0.3949, 0.5909, 1.2553],
[ 2.1078, 0.8691, 0.1411, -0.7530, 0.3073],
[-0.1064, 0.2434, -1.1437, 0.8329, 1.8466],
[ 0.2980, 0.2673, 2.1727, -2.3646, 0.1622]],
[[-0.0562, 2.1093, 1.0785, -0.0582, -0.2702],
[ 0.4585, -0.5435, -0.4719, -1.3152, 1.0080],
[-0.7523, 0.0699, 0.9765, -1.9854, 0.9020],
[-1.6508, -1.6940, 0.7135, -2.2022, -1.4903]],
[[-0.2123, -0.9072, -0.0978, 1.1560, 0.0124],
[-1.1765, 0.8963, -0.4978, -0.3477, -0.5152],
[-0.5168, 0.2212, 0.5939, -1.5076, -0.3851],
[-1.6386, -0.3103, -1.0863, -1.0399, 0.1202]]]])