ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

PyTorch学习笔记——(4)autograd.grad()函数和backward()函数介绍及使用

2021-02-16 21:00:22  阅读:425  来源: 互联网

标签:loss 函数 autograd torch PyTorch 梯度 backward grad


目录

1、torch.autograd.grad()

torch.autograd.grad(
		outputs, 
		inputs, 
		grad_outputs=None, 
		retain_graph=None, 
		create_graph=False, 
		only_inputs=True, 
		allow_unused=False)
  • 参数:
    • outputs: 结果节点,即被求导数
    • inputs: 叶子节点
    • grad_outputs: 类似于backward方法中的grad_tensors
    • retain_graph: 同上
    • create_graph: 同上
    • only_inputs: 默认为True, 如果为True, 则只会返回指定input的梯度值。 若为False,则会计算所有叶子节点的梯度,并且将计算得到的梯度累加到各自的.grad属性上去。
    • allow_unused: 默认为False, 即必须要指定input,如果没有指定的话则报错。

用一个最简单的例子说明:

现在有一个函数: y = w ∗ x y=w*x y=w∗x其中, x x x为输入数据, w w w为可训练参数, y y y为预测值。我们定义损失函数为: l o s s = ( y − w ∗ x ) 2 loss = \sqrt {{{(y - w*x)}^2}} loss=(y−w∗x)2 ​现在求 l o s s loss loss对 w w w的梯度,应该怎么做呢?

答:

  • 1、准备数据:
x = torch.ones(1) # 输入数据
w = torch.full([1], 2.) # 初始化训练参数
y = torch.ones(1) # 标签数据
  • 2、计算损失:
loss = F.mse_loss(y, x*w)  # 计算mse损失
  • 3、使用torch.autograd.grad()函数对参数w求导:
torch.autograd.grad(mse, w) # 错误,发现w不能求导,因为我们们没指定w是能求导的,所以出错了
# 那怎么做呢?接着看:
w.requires_grad_() # 指定w这个参数需要求梯度
# 然后我们再试一试:
torch.autograd.grad(mse, w) 
"""
发现还是出错,这是为啥啊,因为pytorch每次有了计算梯度的参数,那么就会计算一个动态图,
所以我们前面的所有步骤都要重新来一遍。
"""

# 重新来一遍:
w.requires_grad_() # 指定w这个参数需要求梯度,当然在初始化w的时候指定requires_grad=True也是可以的
loss = F.mse_loss(y, x*w) # 求mse误差
torch.autograd.grad(mse, w) # 这个就求出了loss对w的导数了

上面这个函数只能对指定的参数求导,那么我们要是想一次求出所有参数的导数,我们应该怎么做呢?
接着看backward()函数。

2、.torch.autograd.backward()

torch.autograd.backward(
		tensors, 
		grad_tensors=None, 
		retain_graph=None, 
		create_graph=False, 
		grad_variables=None)
  • 参数:
    • tensor: 用于计算梯度的tensor。也就是说这两种方式是等价的: torch.autograd.backward(z) == z.backward()
    • grad_tensors: 在计算矩阵的梯度时会用到。他其实也是一个tensor,shape一般需要和前面的tensor保持一致。
    • retain_graph: 通常在调用一次backward后,pytorch会自动把计算图销毁,所以要想对某个变量重复调用backward,则需要将该参数设置为True
    • create_graph: 当设置为True的时候可以用来计算更高阶的梯度
    • grad_variables: 这个官方说法是grad_variables’ is deprecated. Use ‘grad_tensors’ instead.也就是说这个参数后面版本中应该会丢弃,直接使用grad_tensors就好了。

第一个方式只是对单独的一个参数进行求导,下面我们使用backward()来对动态图的所有参数一次性求导。

例子:

# 1.准备数据
x = torch.ones(2) # 输入特征数据
w = torch.full([2], 2., requires_grad=True) # 初始化训练参数
y = torch.ones_like(x) # 标签数据

# 2.求mse误差
loss = F.mse_loss(y, x*w) # 这个是个标量

# 3.求梯度
mse.backward() # 动态图所有参数的梯度都计算了,但是不会显示出来。注意:通常在调用一次backward后,
# pytorch会自动把计算图销毁,所以要想对某个变量重复调用backward,则需要将retain_graph参数设置为True

# 4.获取梯度
w.grad
# 输出:
tensor([1., 1.])

上面的损失loss我注释里面说是标量,那要不是标量怎么弄的呢?看一个例子:

a = torch.randn(4) # 初始化
a.requires_grad_() # 指定可求导

p = F.softmax(a, dim=0) # 经过sofrmax函数,输出是[1,4]

p.backward(torch.ones(4)) # 里面的参数必须指定,不然报错

这里的P是多维的向量,里面要加参数grad_tensors=torch.ones(4)

为啥:这个知乎的解释感觉是对的:https://zhuanlan.zhihu.com/p/83172023

标签:loss,函数,autograd,torch,PyTorch,梯度,backward,grad
来源: https://blog.csdn.net/weixin_45901519/article/details/113813934

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有