zoukankan      html  css  js  c++  java
  • 0501-Variable

    0501-Variable

    pytorch完整教程目录:https://www.cnblogs.com/nickchen121/p/14662511.html

    一、Variable

    1.1 Variable 的数据结构

    autograd 模块的核心数据结构是 Variable,它是对 tensor 的封装,并且会记录 tensor 的操作记录用来构建计算图。Variable 的数据结构如下图所示:

    上图主要包含三个属性:

    • data:保存 variable 所包含的 tensor
    • grad:保存 data 对应的梯度,grad 也是 variable,而非 tensor,它与 data 形状一致
    • grad_fn:指向一个 Function,记录 variable 的操作历史,即它是什么操作的输出,用来构建计算图。如果某一变量是用户创建的,则它为叶子节点,对应的 grad_fn 为 None

    Variable 的构造函数需要传入 tensor,也有两个可选的参数:

    • requires_grad(bool):是否需要对该 Variable 求导
    • volatile(bool):设置为 True,构建在该 Variable 之上的图都不会求导

    1.2 反向传播

    Variable 支持大部分 tensor 支持的函数,但不支持部分 inplace 函数,因为它们会修改 tensor 自身,然而在反向传播中,Variable 需要缓存原来的 tensor 计算梯度。如果想要计算各个 Variable 的梯度,只需要调用根结点的 backward 方法,autograd 则会自动沿着计算图反向传播,计算每一个叶子节点的梯度。

    variable.backward(grad_variable=None, retain_fraph=None, create_graph=None)的参数解释如下:

    • grad_variables:形状与 Variable 一直,对于 y.backward(),grad_variables 相当于链式法则(frac{partial{z}}{partial{x}} = frac{partial{z}}{partial{y}}frac{partial{y}}{partial{x}})。grad_variables 也可以是 tensor 或序列
    • retain_graph:反向传播会缓存一些中间结果,反向传播之后,这些缓存就会清除,可通过这个参数指定不清除缓存,用来多次反向传播
    • create_graph:对反向传播过程中再次构建计算图
    import torch as t
    from torch.autograd import Variable as V
    
    a = V(t.ones(3, 4), requires_grad=True)
    a
    
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], requires_grad=True)
    
    b = V(t.zeros(3, 4))
    b
    
    tensor([[0., 0., 0., 0.],
            [0., 0., 0., 0.],
            [0., 0., 0., 0.]])
    
    c = a.add(b)  # variable 函数的使用和 tensor 一致,等同于 c=a+b
    c
    
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], grad_fn=<AddBackward0>)
    
    # 注:虽然没有指定 c 需要求导,但 c 依赖于 a,由于 a 需要求导,因此 c 的 requeires_grad 默认设置为 True
    a.requires_grad, b.requires_grad, c.requires_grad
    
    (True, False, True)
    
    # 注:`c.data.sum()`是在去 data 后变为 tensor,从 tensor 计算sum;`c.sum()`计算后仍然是 variable
    d = c.sum()
    d.backward()  # 反向传播
    
    a.grad
    
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]])
    
    # 由用户创建的 Variable 属于叶子节点,对应的 grad_fn 是 None
    a.is_leaf, b.is_leaf, c.is_leaf
    
    (True, True, False)
    
    # 虽然 `c.requires_grad=True`,但是它的梯度计算完之后就会被释放
    c.retain_grad()  # 对于非叶节点求导,需进行保存,否则会被自动释放,这里我们先保存然后再查看,如果没有这一行,会报错
    c.grad is None
    
    True
    

    1.3 autograd 求导数和手动求导数

    通过对函数(y=x^2e^x)求导,我们可以看看 autograd 求导数和自己写个方法求导数的区别。这个函数的导数如下:

    [frac{dy}{dx}=2xe^x+x^2e^x ]

    def f(x):
        """计算 y"""
        y = x**2 * t.exp(x)
        return y
    
    
    def grad_f(x):
        """手动对函数求导"""
        dx = 2 * x * t.exp(x) + x**2 * t.exp(x)
        return dx
    
    
    x = V(t.randn(3, 4), requires_grad=True)
    y = f(x)
    y
    
    tensor([[0.1456, 0.0344, 0.5350, 0.0165],
            [0.9979, 0.3471, 0.5367, 0.4838],
            [0.2595, 0.0010, 0.2002, 0.2058]], grad_fn=<MulBackward0>)
    
    y_grad_variables = t.ones(
        y.size())  # 由于dz/dy=1,并且grad_variables 形状需要与 y 一致,详解看下面的 3.4 小节
    y.backward(y_grad_variables)
    x.grad
    
    tensor([[ 1.0434, -0.3003, -0.0624,  0.2895],
            [ 3.8373,  1.8350,  0.0467, -0.2063],
            [-0.4456,  0.0655, -0.4609, -0.4604]])
    
    grad_f(x)  # autograd 计算的结果和利用公式计算的结果一致
    
    tensor([[ 1.0434, -0.3003, -0.0624,  0.2895],
            [ 3.8373,  1.8350,  0.0467, -0.2063],
            [-0.4456,  0.0655, -0.4609, -0.4604]], grad_fn=<AddBackward0>)
  • 相关阅读:
    固定sql语句传参批量查询数据库脚本
    超多行数据纵向编辑
    takes 3 positional arguments but 4 were given错误
    使用PMD进行代码审查(转)
    WebADI应用到Office 2016 64-bit
    SVN 提交代码时强制加入注释内容
    DOCKER初体验
    "make_path" is not exported by the File::Path modul
    perl 调用shell脚本
    scp 上传文件到多个服务器节点
  • 原文地址:https://www.cnblogs.com/nickchen121/p/14686103.html
Copyright © 2011-2022 走看看