pytorch基础知识-.backward()求导和softmax介绍

2019-11-17 22:38:23 浏览数 (1)

对比前文,更简便的办法是使用.backward()函数进行求导

以代码示例

代码语言:javascript复制
x = torch.ones(1)
w = torch.full([1], 2, requires_grad=True)
# 首先构建tensor
# 构建动态图,完成MSE的构建
mse = F.mse_loss(torch.ones(1), x*w)
# 对其求导时直接对设定的loss使用.backward()函数
mse.backward()
# 对设定的loss信息进行向后传递,注意:pytorch在前向传播时会自动记录传播路径
# 会记录路径上所有gradient的方法,使用 参数.grad函数即可输出相应的求导信息
print(w.grad)

输出

代码语言:javascript复制
tensor([2.])

这种.backward()方法更为简洁,以后在编写代码时也多采用这种方法。

在此总结两种求导方法

(1).torch.autograd.grad(loss, [w1, w2, ...])

该函数返回的是əloss/əw1, əloss/əw2。

(2) loss.backward()法

直接调用之前的梯度信息

写入w1.grad, w2.grad即可输出

下面介绍经常使用的softmax函数

Softmax(全称:soft version of max)常与crossentropy(交叉熵)搭配连用。

上图中假设有三个输出,分别是2.0、1.0和0.1,如果将数值转移成概率的话,希望概率最大的值作为label。即我们希望将最大值2.0所对应的label作为相应索引输出。那么如何进行按照probilities作为概率输出呢?

按照之前所讲的sigmoid函数压缩成[0~1],但对于分类问题来说,物体均具有概率属性,按此方法输出的所有概率之和无法满足等于1的要求(P(0) P(1) P(2) = 1)。

因此为解决此类问题,这里引入了softmax函数。

这里进行了操作 e2/(e2 e1 e0.1) = 0.7,e1/(e2 e1 e0.1) = 0.2,e0.1/(e2 e1 e0.1)=0.1。

这样每个节点都在0至1之间。另外这里注意,softmax具有差距放大功能。如原2.0与1.0是两倍的关系,经过softmax操作后,变为0.7与0.2,呈3.5倍的关系。

对softmax函数进行求导,首先写出其函数式

进行求导

另eai为g(x),另分母eak为h(x)。

当i与j相等时:

当i与j不相等时:

对以上求导过程进行总结

这里注意,由于pi和pj均在[0,1]范围内。故pi(1-pj)乘积大于0,而-pi*pj的乘积小于0。

这里使用代码举例

代码语言:javascript复制
import torch
import torch.nn.functional as F

a = torch.rand(3, requires_grad=True)
print(a)

p = F.softmax(a, dim=0)
# 指定dim维度进行sfotmax操作

print('softmax:', p)

print(torch.autograd.grad(p[1], [a]))
# 注意loss必须为长度为1的值,这里由于p是dim=1,长度为3的值,因此取p[1]。

输出为

代码语言:javascript复制
tensor([0.1683, 0.6142, 0.7754], requires_grad=True)
softmax: tensor([0.2274, 0.3552, 0.4174], grad_fn=<SoftmaxBackward>)
(tensor([-0.0808,  0.2290, -0.1483]),)

这里进行了əp1/əai的操作,由于a是[0, 2]的tensor,结果返回了[1, 3]的矩阵。当i=1时,梯度信息为正,这在前文中有所提到。

0 人点赞