【PyTorch基础教程2】自动求导机制(学不会来打我啊)
文章目录
- 第一部分:深度学习和机器学习
- 一、机器学习任务
- 二、ML和DL区别
- (1)数据加载
- (2)模型实现
- (3)训练过程
- 第二部分:Pytorch部分
- 一、学习资源
- 二、自动求导机制
- 2.1 torch.Tensor类
- 2.2 Function类
- 2.3 雅克比矩阵
- 2.4 代码栗子
- 三、基本配置
- 3.1 导包
- 3.2 超参数设置
- 3.3 GPU的设置
- Reference
第一部分:深度学习和机器学习
一、机器学习任务
回顾我们在完成一项机器学习任务时的步骤:
(1)首先需要对数据进行预处理,其中重要的步骤包括数据格式的统一和必要的数据变换,同时划分训练集和测试集。
(2)接下来选择模型,并设定损失函数和优化函数,以及对应的超参数(当然可以使用sklearn
这样的机器学习库中模型自带的损失函数和优化器)。
(3)最后用模型去拟合训练集数据,并在验证集/测试集上计算模型表现。
二、ML和DL区别
(1)数据加载
深度学习和机器学习在流程上类似,但在代码实现上有较大的差异。
(1)首先,由于深度学习所需的样本量很大,一次加载全部数据运行可能会超出内存容量而无法实现;
(2)同时还有批(batch)训练等提高模型表现的策略,需要每次训练读取固定数量的样本送入模型中训练,因此深度学习在数据加载上需要有专门的设计。
(2)模型实现
在模型实现上,深度学习和机器学习也有很大差异:
由于深度神经网络层数往往较多,同时会有一些用于实现特定功能的层(如卷积层、池化层、批正则化层、LSTM层等),因此深度神经网络往往需要“逐层”搭建,或者预先定义好可以实现特定功能的模块,再把这些模块组装起来。这种“定制化”的模型构建方式能够充分保证模型的灵活性,也对代码实现提出了新的要求。
接下来是损失函数和优化器的设定。这部分和经典机器学习的实现是类似的。但由于模型设定的灵活性,因此损失函数和优化器要能够保证反向传播能够在用户自行定义的模型结构上实现。
(3)训练过程
上述步骤完成后就可以开始训练了。
(1)GPU的概念和GPU用于并行计算加速的功能,不过程序默认是在CPU上运行的,因此在代码实现中,需要把模型和数据“放到”GPU上去做运算,同时还需要保证损失函数和优化器能够在GPU上工作。
(2)如果使用多张GPU进行训练,还需要考虑模型和数据分配、整合的问题。
(3)后续计算一些指标还需要把数据“放回”CPU。这里涉及到了一系列有关于GPU的配置和操作。
(4)深度学习中训练和验证过程最大的特点在于读入数据是按批的,每次读入一个批次的数据,放入GPU中训练,然后将损失函数反向传播回网络最前面的层,同时使用优化器调整网络参数。这里会涉及到各个模块配合的问题。训练/验证后还需要根据设定好的指标计算模型表现。
经过以上步骤,一个深度学习任务就完成了。
第二部分:Pytorch部分
一、学习资源
(1) Awesome-pytorch-list:目前已获12K Star,包含了NLP,CV,常见库,论文实现以及Pytorch的其他项目。
(2)PyTorch官方文档:官方发布的文档,十分丰富。
(3)Pytorch-handbook:GitHub上已经收获14.8K,pytorch手中书。
(4)PyTorch官方社区:在这里你可以和开发pytorch的人们进行交流。
除此之外,还有很多学习pytorch的资源,b站,stackoverflow,知乎等多多利用。
二、自动求导机制
PyTorch 中,所有神经网络的核心是 autograd
包。autograd
包为张量上的所有操作提供了自动求导机制。它是一个在运行时定义 ( define-by-run )的框架,这意味着反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。
2.1 torch.Tensor类
torch.Tensor
是这个包的核心类。如果设置它的属性.requires_grad
为 True
,那么它将会追踪对于该张量的所有操作。当完成计算后可以通过调用.backward()
,来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad
属性。
注意:在 y.backward()
时,如果 y 是标量,则不需要为 backward() 传入任何参数;否则,即如果 y 不是标量,需要传入一个与 y 同形的Tensor。
要阻止一个张量被跟踪历史,可以调用
.detach()
方法将其与计算历史分离,并阻止它未来的计算记录被跟踪。为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():
中。在评估模型时特别有用,因为模型可能具有requires_grad = True
的可训练的参数,但是我们不需要在此过程中对他们进行梯度计算。
2.2 Function类
还有一个类对于autograd
的实现非常重要:Function
。Tensor
和Function
互相连接生成了一个无环图 (acyclic graph),它编码了完整的计算历史。每个张量都有一个.grad_fn
属性,该属性引用了创建 Tensor
自身的Function
(除非这个张量是用户手动创建的,即这个张量的grad_fn
是 None
)。
如果需要计算导数,可以在 Tensor
上调用 .backward()
。如果Tensor
是一个标量(即它包含一个元素的数据),则不需要为 backward()
指定任何参数,但是如果它有更多的元素,则需要指定一个gradient
参数,该参数是形状匹配的张量。
2.3 雅克比矩阵
数学上,若有向量函数 y ⃗ = f ( x ⃗ ) \vec{y}=f(\vec{x}) y =f(x ),那么 y ⃗ \vec{y} y 关于 x ⃗ \vec{x} x 的梯度就是一个雅可比矩阵:
J = ( ∂ y 1 ∂ x 1 ⋯ ∂ y 1 ∂ x n ⋮ ⋱ ⋮ ∂ y m ∂ x 1 ⋯ ∂ y m ∂ x n ) J=\left(\begin{array}{ccc}\frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}} \\ \vdots & \ddots & \vdots \\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}}\end{array}\right) J=⎝⎜⎛∂x1∂y1⋮∂x1∂ym⋯⋱⋯∂xn∂y1⋮∂xn∂ym⎠⎟⎞
而 torch.autograd
这个包就是用来计算一些雅可比矩阵的乘积的。例如,如果 v v v 是一个标量函数 l = g ( y ⃗ ) l = g(\vec{y}) l=g(y ) 的梯度:
v = ( ∂ l ∂ y 1 ⋯ ∂ l ∂ y m ) v=\left(\begin{array}{lll}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right) v=(∂y1∂l⋯∂ym∂l)
由链式法则,我们可以得到:
v J = ( ∂ l ∂ y 1 ⋯ ∂ l ∂ y m ) ( ∂ y 1 ∂ x 1 ⋯ ∂ y 1 ∂ x n ⋮ ⋱ ⋮ ∂ y m ∂ x 1 ⋯ ∂ y m ∂ x n ) = ( ∂ l ∂ x 1 ⋯ ∂ l ∂ x n ) v J=\left(\begin{array}{lll}\frac{\partial l}{\partial y_{1}} & \cdots & \frac{\partial l}{\partial y_{m}}\end{array}\right)\left(\begin{array}{ccc}\frac{\partial y_{1}}{\partial x_{1}} & \cdots & \frac{\partial y_{1}}{\partial x_{n}} \\ \vdots & \ddots & \vdots \\ \frac{\partial y_{m}}{\partial x_{1}} & \cdots & \frac{\partial y_{m}}{\partial x_{n}}\end{array}\right)=\left(\begin{array}{lll}\frac{\partial l}{\partial x_{1}} & \cdots & \frac{\partial l}{\partial x_{n}}\end{array}\right) vJ=(∂y1∂l⋯∂ym∂l)⎝⎜⎛∂x1∂y1⋮∂x1∂ym⋯⋱⋯∂xn∂y1⋮∂xn∂ym⎠⎟⎞=(∂x1∂l⋯∂xn∂l)
注意:grad
在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。
2.4 代码栗子
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 15 21:07:32 2021@author: 86493
"""
import torch
# require_grad=True用来追踪计算历史
x = torch.ones(2, 2, requires_grad = True)
print(x)
print('-' * 50)# 对张量作指数运算
y = x ** 2
print(y)
# y是计算的结果,所以又grad_fn属性
print(y.grad_fn)
print('-' * 50)z = y * y * 3
out = z.mean() # 计算所有元素的平均值
print("z:", z)
print("out:", out)
print('-' * 50)# requires_grad默认为False
a = torch.randn(2, 2)
print("初始的a值为:\n", a)
a = ((a * 3) / (a - 1))
print("运算后的a值为:\n", a)
print(a.requires_grad) # 默认为False
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn) # b是计算的结果,所有它有grad_fn属性
print('-' * 50)# ==================================
# 求梯度
out.backward() # out是一个标量
print(x.grad) # 输入导数d(out)/dx
print('-' *50)# 再来反向传播,注意grad是累加的(加多一次梯度)
# out2.backward()
# print(x.grad)out3 = x.sum()
# 一般在反向传播前把梯度清零(以防累加)
x.grad.data.zero_()
out3.backward()
print(x.grad)
print('-' *50)# 雅克比向量积
x = torch.randn(3, requires_grad = True)
print(x)
y = x * 2
i = 0
# norm是求该tensor的L2范数
while y.data.norm() < 1000:y = y * 2i = i + 1
print("y:\n", y, '\n')
print("i:", i)v = torch.tensor([0.1, 1.0, 0.0001],dtype = torch.float)
y.backward(v)
print("x.grad:\n", x.grad)# 可以通过将代码块包装在with torch.no_grad()中
# 来阻止autograd跟踪设置了requires_grad=True
print(x.requires_grad)
print((x ** 2).requires_grad)with torch.no_grad():print((x ** 2).requires_grad)
print('-' *50)# 想修改tensor的数值,又不希望被autograd记录
# 即不会影响反向传播,可以对tensor.data操作
x = torch.ones(1, requires_grad = True)
print("x: ", x)
print(x.data) # 还是一个tensor
# 但是已经独立于计算图之外
print(x.data.requires_grad)y = 2 * x
# 只改变了值,不会记录在计算图,所以不会影响梯度传播
x.data *= 100y.backward()
# 更改data值也会影响tensor的值
print(x)
print(x.grad)
结果为:
tensor([[1., 1.],[1., 1.]], requires_grad=True)
--------------------------------------------------
tensor([[1., 1.],[1., 1.]], grad_fn=<PowBackward0>)
<PowBackward0 object at 0x000001D74AEFBE50>
--------------------------------------------------
z: tensor([[3., 3.],[3., 3.]], grad_fn=<MulBackward0>)
out: tensor(3., grad_fn=<MeanBackward0>)
--------------------------------------------------
初始的a值为:tensor([[-0.5364, -0.5926],[-0.5702, -0.7497]])
运算后的a值为:tensor([[1.0474, 1.1163],[1.0894, 1.2855]])
False
True
<SumBackward0 object at 0x000001D745FEDF70>
--------------------------------------------------
tensor([[3., 3.],[3., 3.]])
--------------------------------------------------
tensor([[1., 1.],[1., 1.]])
--------------------------------------------------
tensor([ 0.4216, 0.1233, -0.3729], requires_grad=True)
y:tensor([ 863.4903, 252.5478, -763.7181], grad_fn=<MulBackward0>) i: 10
x.grad:tensor([2.0480e+02, 2.0480e+03, 2.0480e-01])
True
True
False
--------------------------------------------------
x: tensor([1.], requires_grad=True)
tensor([1.])
Falserunfile('D:/桌面文件/matrix/code/Torch/grad.py', wdir='D:/桌面文件/matrix/code/Torch')
tensor([[1., 1.],[1., 1.]], requires_grad=True)
--------------------------------------------------
tensor([[1., 1.],[1., 1.]], grad_fn=<PowBackward0>)
<PowBackward0 object at 0x000001D74AEFBA30>
--------------------------------------------------
z: tensor([[3., 3.],[3., 3.]], grad_fn=<MulBackward0>)
out: tensor(3., grad_fn=<MeanBackward0>)
--------------------------------------------------
初始的a值为:tensor([[ 0.1064, -1.0084],[-0.2516, -0.4749]])
运算后的a值为:tensor([[-0.3570, 1.5063],[ 0.6030, 0.9660]])
False
True
<SumBackward0 object at 0x000001D745593FD0>
--------------------------------------------------
tensor([[3., 3.],[3., 3.]])
--------------------------------------------------
tensor([[1., 1.],[1., 1.]])
--------------------------------------------------
tensor([-0.8706, -1.1828, -0.8192], requires_grad=True)
y:tensor([ -891.5447, -1211.1826, -838.8481], grad_fn=<MulBackward0>) i: 9
x.grad:tensor([1.0240e+02, 1.0240e+03, 1.0240e-01])
True
True
False
--------------------------------------------------
x: tensor([1.], requires_grad=True)
tensor([1.])
False
tensor([100.], requires_grad=True)
tensor([2.])
三、基本配置
3.1 导包
常见的有torch、torch.nn、torch.utils.data.Dataset、torch.utils.data.DataLoader、torch.optimizer、numpy、os等,具体可以在官网查对应的API,另外还有比如:
- 涉及到表格信息的读入很可能用到pandas;
- 对于不同的项目可能还需要导入一些更上层的包如cv2等。
- 如果涉及可视化还会用到matplotlib、seaborn等。
- 涉及到下游分析和指标计算也常用到sklearn
import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
import torch.optim as optimizer
3.2 超参数设置
- batch size
- 初始学习率(初始)
- 训练次数(max_epochs)
- GPU配置
batch_size = 16
lr = 1e-4
max_epochs = 100
3.3 GPU的设置
记得提前import os
。
# GPU设置
import os
# 方案一:使用os.environ,如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0.1'# 方案二:使用"device"
# 后续要使用GPU的变量用.to(device)
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
Reference
(1)2.5.4 PyTorch中的非标量反向传播
(2)datawhale的pytorch笔记
【PyTorch基础教程2】自动求导机制(学不会来打我啊)相关推荐
- PyTorch的计算图和自动求导机制
文章目录 PyTorch的计算图和自动求导机制 自动求导机制简介 自动求导机制实例 梯度函数的使用 计算图构建的启用和禁用 总结 PyTorch的计算图和自动求导机制 自动求导机制简介 PyTorch ...
- pytorch教程之自动求导机制(AUTOGRAD)-从梯度和Jacobian矩阵讲起
文章目录 1. 梯度和Jacobian矩阵 2. pytorch求变量导数的过程 1. 梯度和Jacobian矩阵 设f(x)∈R1f(x)\in R^1f(x)∈R1是关于向量x∈Rnx\in R^ ...
- Pytorch教程入门系列4----Autograd自动求导机制
系列文章目录 文章目录 系列文章目录 前言 一.Autograd是什么? 二.Autograd的使用方法 1.在tensor中指定 2.重要属性 三.Autograd的进阶知识 1.动态计算图 2.梯 ...
- Pytorch学习(一)—— 自动求导机制
现在对 CNN 有了一定的了解,同时在 GitHub 上找了几个 examples 来学习,对网络的搭建有了笼统地认识,但是发现有好多基础 pytorch 的知识需要补习,所以慢慢从官网 API 进行 ...
- PyTorch 笔记Ⅱ——PyTorch 自动求导机制
文章目录 Autograd: 自动求导机制 张量(Tensor) 梯度 使用PyTorch计算梯度数值 Autograd 简单的自动求导 复杂的自动求导 Autograd 过程解析 扩展Autogra ...
- pytorch如何计算导数_Pytorch的自动求导机制与使用方法(一)
本文以线性模型为例,讲解线性模型的求解的pytorch梯度实现方法. 要注意几个问题:在PyTorch 0.4.0版本之后,Variable类已经被禁用了,所有的torch.Tensor与torch. ...
- Pytorch Autograd (自动求导机制)
Introduce Pytorch Autograd库 (自动求导机制) 是训练神经网络时,反向误差传播(BP)算法的核心. 本文通过logistic回归模型来介绍Pytorch的自动求导机制.首先, ...
- 【PyTorch学习(三)】Aurograd自动求导机制总结
Aurograd自动求导机制总结 PyTorch中,所有神经网络的核心是 autograd 包.autograd 包为tensor上的所有操作提供了自动求导机制.它是一个在运行时定义(define- ...
- 深度学习框架 TensorFlow:张量、自动求导机制、tf.keras模块(Model、layers、losses、optimizer、metrics)、多层感知机(即多层全连接神经网络 MLP)
日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 安装 TensorFlow2.CUDA10.cuDNN7.6. ...
最新文章
- 为x86 CPU自动调度神经网络
- 对比自监督学习浪潮迅猛来袭,你准备好了吗?
- [转]Hyper-V功能大跃进 或引发市场洗牌
- Linux Shell脚本攻略学习总结:三
- Linux下搭建SVN+版本冲突
- 全栈工程师之路(二)—— JavaScript(网页前端脚本语言)
- linux apt-get 源,Ubuntu应用之——apt-get更改源地址
- ”盒模型“之如何防止边框和内边距把元素撑开
- ch340串口驱动_关于串口下载问题和超时
- [python-thirdLib] Python中第三方的用于解析HTML的库:BeautifulSoup
- CentOS4.4下安装jdk1.5
- 语法分析—自上而下分析
- 第一步:Spring访问数据库(jdbcTemplate)
- Vue 导出excel 导出多个sheet
- Python 情人节超强技能 导出微信聊天记录生成词云,深入讲解Python
- temp不停生成临时文件 win10_桌面出现temp文件夹|桌面出现大量临时文件|win10桌面temp文件夹是什么...
- Cisco路由器内部网关协议(IGP)实验:OSPF
- 充电计划 -- 浏览器工作流程、渲染流程
- 相机计算坐标公式_机器视觉系统坐标标定与计算方法
- 月薪80k阿里架构师:给迷茫的JAVA一些中肯建议(附学习路线图)