实践·pytorch梯度计算
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实践·pytorch梯度计算相关的知识,希望对你有一定的参考价值。
参考技术Apytorch梯度机制,计算梯度注意事项
pytorch,autograd,tensor,自动微分,张量,梯度
在一些优化算法中,常常需要计算函数的梯度,在pytorch可以借助autograd机制来自动计算梯度值。
假设 ,关于 的梯度记为 , 是关于变量 的函数,其梯度 是随着 的值变化而变化的,决定梯度的除了 自身的值以外还有施加在 上的运算。因此,关注梯度就是关注两个东西,求哪个 变量 的梯度,该变量上被施加了哪种 运算 。
首先看 变量 :在pytorch中把梯度作为一个固有属性结合进张量(tensor),任何一个tensor类型的变量都有梯度(grad)属性,再结合一般场景下的需要,pytorch把 tensor 类型定义为一个对象,包括5个属性,分别对应 data (变量本身的值), grad (梯度值), requires_grad (是否需要梯度,很多场景都不需要求变量的微分), grad_fn (生成该变量结果的运算,即这个值通过什么运算来的), is_leaf (是否叶子节点,叶子才帮你算梯度)。
接着看 运算 :在pytorch中没有显式的给出梯度函数表达,而是算出梯度值,存放在tensor类型变量的grad属性中,那么运算也一样用结果来表达,假设 ,这里的 就承载了运算的结果,因此需要求 的梯度值时就对 使用 backward() 方法来计算 的梯度。
上面提到计算梯度的两个要素: 变量 和 运算 ,对应的pytorch机制是 tensor 对象和 backward 方法。因此计算梯度就是学会怎么用这俩货。具体的例子这边不写,各位大神写的很多了,不当搬运工了,推荐 参考资料3 , 参考资料2 。这里说明两点,然后总结个过程。
(1)可求梯度的条件
从上面的叙述知道,一个变量有5个属性,要求这个变量可以求梯度,需要满足2个属性为真,requires_grad=True,is_leaf=True。在声明变量的时候声明requires_grad=True就可以了。在实践过程中如果发现梯度没法计算,要查一下这两个属性。
(2)回传结果类型
大部分情况是对标量求梯度,也是在 中, 是标量的情况,如果 向量或矩阵,也可以求梯度,此时本质上也是按分量一个一个来,因此要给backward()加个参数,一般情况下该参数的形状和 一样,每一个位置的值指示每个分量的梯度权重,多数情况就是全部设置为1。
(3)一般过程
仍然假设求 的关于 的梯度,首先设置声明tensor类型变量 ,声明的时候需要设置参数requires_grad=True;接下来计算出 ,这里的 是用来表示函数运算过程,最后使用 ,如果 非标量,就加个参数,假设为 , 的形状与 相同,此时使用的是 ,要的梯度值可以通过 获得。
单独写个注意事项,计算变量 的梯度时, 的属性有可能会变化,比如需要对 进行迭代,假设为 ,那么 的requires_grad和is_leaf属性会变化,变得不可求梯度,那怎么办呢,其实程序迭代时只需要改变值就好了,使用 就可以了。
[1] https://pytorch.org/docs/1.3.1/index.html
[2] https://blog.csdn.net/qq_27825451/article/details/89393332
[3] https://www.cnblogs.com/marsggbo/p/11549631.html
Pytorch自动求解梯度
要理解Pytorch求解梯度,首先需要理解Pytorch当中的计算图的概念,在计算图当中每一个Variable都代表的一个节点,每一个节点就可以代表一个神经元,我们只有将变量放入节点当中才可以对节点当中的变量求解梯度,假设我们有一个矩阵:
1., 2., 3.
4., 5., 6.
我们将这个矩阵(二维张量)首先在Pytorch当中初始化,并且将其放入计算图当中的节点当中,在Pytorch当中,一个节点用Variable来表示,因此可以编写如下代码:
import torch from torch.autograd import Variable # 我们创建的是一个二维张量(即矩阵)而不是标量,因此会报错 # 在Pytorch当中,仅允许标量对标量或者 标量对向量(或者张量)求解偏导数 x=Variable(torch.Tensor([[1., 2., 3.], [4., 5., 6.]]), requires_grad=True)
在节点当中,拥有requires_grad的参数,系统默认是False,也就是不能对其中的变量求解梯度,但是我们需要里面变量的梯度,因此需要将整个参数命名为True。
最后我们写出其他变量有关x的表达式:
y=2*x*x+2
j=y.mean()
这样就得到了j的值,这是一个标量,因为mean表示的求解平均值,在Pytorch当中只能够标量对标量,或者标量对张量求解偏导数,否则就会报错。
现在我们的计算图模型就搭建完毕了,整个模型当中只有一个节点,其他的表示相当于神经元当中的权重,以及J代表loss函数,我们调用Pytorch当中的反向传播函数backward(),对x关于j的梯度进行求解,代码如下:
j.backward()
这样梯度就求解完毕了,我们打印出x关于j的梯度的值,后面的参数x.grad表示求解出来的x的梯度大小:
print("x的梯度是:",x.grad)
输出:
x的梯度是:
tensor([[0.6667, 1.3333, 2.0000], [2.6667, 3.3333, 4.0000]]
得解!
以上是关于实践·pytorch梯度计算的主要内容,如果未能解决你的问题,请参考以下文章