热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

pytorch中autograd.grad()函数的用法说明

这篇文章主要介绍了pytorch中autograd.grad()函数的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

我们在用神经网络求解PDE时, 经常要用到输出值对输入变量不是Weights和Biases)求导; 在训练WGAN-GP 时, 也会用到网络对输入变量的求导。

以上两种需求, 均可以用pytorch 中的autograd.grad() 函数实现。

autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False, only_inputs=True, allow_unused=False)

outputs: 求导的因变量(需要求导的函数)

inputs: 求导的自变量

grad_outputs: 如果 outputs为标量,则grad_outputs=None,也就是说,可以不用写; 如果outputs 是向量,则此参数必须写,不写将会报如下错误:

那么此参数究竟代表着什么呢?

先假设 为一维向量, 即可设自变量因变量分别为 , 其对应的 Jacobi 矩阵为

grad_outputs 是一个shape 与 outputs 一致的向量, 即

在给定grad_outputs 之后,真正返回的梯度为

为方便下文叙述我们引入记号

其次假设 ,第i个列向量对应的Jacobi矩阵为

此时的grad_outputs 为(维度与outputs一致)

由第一种情况, 我们有

也就是说对输出变量的列向量求导,再经过权重累加。

沿用第一种情况记号

, 其中每一个 均由第一种方法得出,

即对输入变量列向量求导,之后按照原先顺序排列即可。

retain_graph: True 则保留计算图, False则释放计算图

create_graph: 若要计算高阶导数,则必须选为True

allow_unused: 允许输入变量不进入计算

下面我们看一下具体的例子:

import torch
from torch import autograd
 
x = torch.rand(3, 4)
x.requires_grad_()

观察 x 为

不妨设 y 是 x 所有元素的和, 因为 y是标量,故计算导数不需要设置grad_outputs

y = torch.sum(x)
grads = autograd.grad(outputs=y, inputs=x)[0]
print(grads)

结果为

若y是向量

y = x[:,0] +x[:,1]
# 设置输出权重为1
grad = autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y))[0]
print(grad)
# 设置输出权重为0
grad = autograd.grad(outputs=y, inputs=x, grad_outputs=torch.zeros_like(y))[0]
print(grad)

结果为

最后, 我们通过设置 create_graph=True 来计算二阶导数

y = x ** 2
grad = autograd.grad(outputs=y, inputs=x, grad_outputs=torch.ones_like(y), create_graph=True)[0]
grad2 = autograd.grad(outputs=grad, inputs=x, grad_outputs=torch.ones_like(grad))[0]
print(grad2)

结果为

综上,我们便搞清楚了它的求导机制。

补充:pytorch学习笔记:自动微分机制(backward、torch.autograd.grad)

一、前言

神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情。

而深度学习框架可以帮助我们自动地完成这种求梯度运算。

Pytorch一般通过反向传播 backward方法 实现这种求梯度计算。该方法求得的梯度将存在对应自变量张量的grad属性下。

除此之外,也能够调用torch.autograd.grad函数来实现求梯度计算。

这就是Pytorch的自动微分机制。

二、利用backward方法求导数

backward方法通常在一个标量张量上调用,该方法求得的梯度将存在对应自变量张量的grad属性下。如果调用的张量非标量,则要传入一个和它同形状的gradient参数张量。相当于用该gradient参数张量与调用张量作向量点乘,得到的标量结果再反向传播。

1, 标量的反向传播

import numpy as np 
import torch 
# f(x) = a*x**2 + b*x + c的导数
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c 
y.backward()
dy_dx = x.grad
print(dy_dx)

输出:

tensor(-2.)

2, 非标量的反向传播

import numpy as np 
import torch 
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c 
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
print("x:\n",x)
print("y:\n",y)
y.backward(gradient = gradient)
x_grad = x.grad
print("x_grad:\n",x_grad)

输出:

x:

tensor([[0., 0.],

[1., 2.]], requires_grad=True)

y:

tensor([[1., 1.],

[0., 1.]], grad_fn=)

x_grad:

tensor([[-2., -2.],

[ 0., 2.]])

3, 非标量的反向传播可以用标量的反向传播实现

import numpy as np 
import torch 
# f(x) = a*x**2 + b*x + c
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c 
gradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
z = torch.sum(y*gradient)
print("x:",x)
print("y:",y)
z.backward()
x_grad = x.grad
print("x_grad:\n",x_grad)

输出:

x: tensor([[0., 0.],

[1., 2.]], requires_grad=True)

y: tensor([[1., 1.],

[0., 1.]], grad_fn=)

x_grad:

tensor([[-2., -2.],

[ 0., 2.]])

三、利用autograd.grad方法求导数

import numpy as np 
import torch 
# f(x) = a*x**2 + b*x + c的导数
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c

# create_graph 设置为 True 将允许创建更高阶的导数 
dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
print(dy_dx.data)
# 求二阶导数
dy2_dx2 = torch.autograd.grad(dy_dx,x)[0] 
print(dy2_dx2.data)

输出:

tensor(-2.)

tensor(2.)

import numpy as np 
import torch 
x1 = torch.tensor(1.0,requires_grad = True) # x需要被求导
x2 = torch.tensor(2.0,requires_grad = True)
y1 = x1*x2
y2 = x1+x2

# 允许同时对多个自变量求导数
(dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,
                inputs = [x1,x2],retain_graph = True)
print(dy1_dx1,dy1_dx2)
# 如果有多个因变量,相当于把多个因变量的梯度结果求和
(dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],
            inputs = [x1,x2])
print(dy12_dx1,dy12_dx2)

输出:

tensor(2.) tensor(1.)

tensor(3.) tensor(2.)

四、利用自动微分和优化器求最小值

import numpy as np 
import torch 
# f(x) = a*x**2 + b*x + c的最小值
x = torch.tensor(0.0,requires_grad = True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
optimizer = torch.optim.SGD(params=[x],lr = 0.01)

def f(x):
    result = a*torch.pow(x,2) + b*x + c 
    return(result)
for i in range(500):
    optimizer.zero_grad()
    y = f(x)
    y.backward()
    optimizer.step()   
    
print("y=",f(x).data,";","x=",x.data)

输出:

y= tensor(0.) ; x= tensor(1.0000)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。


推荐阅读
  • 本文介绍了腾讯最近开源的BERT推理模型TurboTransformers,该模型在推理速度上比PyTorch快1~4倍。TurboTransformers采用了分层设计的思想,通过简化问题和加速开发,实现了快速推理能力。同时,文章还探讨了PyTorch在中间层延迟和深度神经网络中存在的问题,并提出了合并计算的解决方案。 ... [详细]
  • 【论文】ICLR 2020 九篇满分论文!!!
    点击上方,选择星标或置顶,每天给你送干货!阅读大概需要11分钟跟随小博主,每天进步一丢丢来自:深度学习技术前沿 ... [详细]
  • 干货 | 携程AI推理性能的自动化优化实践
    作者简介携程度假AI研发团队致力于为携程旅游事业部提供丰富的AI技术产品,其中性能优化组为AI模型提供全方位的优化方案,提升推理性能降低成本࿰ ... [详细]
  • 「爆干7天7夜」入门AI人工智能学习路线一条龙,真的不能再透彻了
    前言应广大粉丝要求,今天迪迦来和大家讲解一下如何去入门人工智能,也算是迪迦对自己学习人工智能这么多年的一个总结吧,本条学习路线并不会那么 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 建立分类感知器二元模型对样本数据进行分类
    本文介绍了建立分类感知器二元模型对样本数据进行分类的方法。通过建立线性模型,使用最小二乘、Logistic回归等方法进行建模,考虑到可能性的大小等因素。通过极大似然估计求得分类器的参数,使用牛顿-拉菲森迭代方法求解方程组。同时介绍了梯度上升算法和牛顿迭代的收敛速度比较。最后给出了公式法和logistic regression的实现示例。 ... [详细]
  • 本博文基于《Amalgamationofproteinsequence,structureandtextualinformationforimprovingprote ... [详细]
  • OCR:用字符识别方法将形状翻译成计算机文字的过程Matlab:商业数学软件;CUDA:CUDA™是一种由NVIDIA推 ... [详细]
  • 3年半巨亏242亿!商汤高估了深度学习,下错了棋?
    转自:新智元三年半研发开支近70亿,累计亏损242亿。AI这门生意好像越来越不好做了。近日,商汤科技已向港交所递交IPO申请。招股书显示& ... [详细]
  • 人工智能推理能力与假设检验
    最近Google的Deepmind开始研究如何让AI做数学题。这个问题的提出非常有启发,逻辑推理,发现新知识的能力应该是强人工智能出现自我意识之前最需要发展的能力。深度学习目前可以 ... [详细]
  • Two Sigma人均22万英镑~
    近期原创文章: ... [详细]
  • 论文阅读:《Bag of Tricks for LongTailed Visual Recognition with Deep Convolutional Neural Networks》
    基于深度卷积神经网络的长尾视觉识别技巧包摘要近年来,挑战性长尾分布上的视觉识别技术取得了很大的进展,主要基于各种复杂的范式(如元学习)。除了这些复杂 ... [详细]
author-avatar
mobiledu2502885407
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有