李沐07自动求导——自学笔记

自动求导

自动求导:计算一个函数在特定值的导数

计算图:
(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]]]])
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值