Datawhale深入浅出PyTorch

深入浅出PyTorch

PyTorch安装与配置

install时的问题

出现Solving environment: failed with initial frozen solve. Retrying with flexible solve:

可能的原因是版本问题,大部分情况下conda update可以解决

Blogs for reference

https://blog.csdn.net/qq_43391414/article/details/124398631

https://blog.csdn.net/weixin_41622348/article/details/100582862

PyTorch基础

张量

Tensor的创建

函数功能
Tensor(sizes)基础构造函数
tensor(data)类似于np.array
ones(sizes)全1
zeros(sizes)全0
eye(sizes)对角为1,其余为0
arange(s,e,step)从s到e,步长为step
linspace(s,e,steps)从s到e,均匀分成step份
rand/randn(sizes)rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布
normal(mean,std)正态分布(均值为mean,标准差是std)
randperm(m)随机排列
full(size,element)一个全为element的tensor

torch.normal — PyTorch 1.12 documentation

Tensor的操作

加法操作:
import torch
# 方式1
y = torch.rand(4, 3) 
print(x + y)

# 方式2
print(torch.add(x, y))

# 方式3 in-place,原值修改
y.add_(x) 
print(y)
索引操作
import torch
x = torch.rand(4,3)
y = x[0,:]
y += 1						# 源tensor也被改了了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YDZRgObu-1657606682874)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220710164621064.png)]

!!!我觉得教程这里怪怪的,讲索引值会跟着修改,框框中打印第二列有点无厘头,应该是打印第一行更好些

改变维度
  1. torch.view()

torch.view()会改变原始张量

x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
  1. torch.reshape()

此函数并不能保证返回的是其拷贝值,所以官方不推荐使用。推荐的方法是我们先用 clone() 创造一个张量副本然后再使用 torch.view()进行函数维度变换 ,从而达到原始张量和副本张量不共享内存的目的

clone() 还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源 Tensor

取值操作

如果我们有一个元素 tensor ,我们可以使用 .item() 来获得这个 value,而不获得其他性质:

import torch
x = torch.randn(1) 
print(type(x)) 
print(type(x.item()))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B0gDQ5Pg-1657606682876)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220710165641023.png)]

!!!这里的排版有问题

广播机制(Broadcasting)

当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。

x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
#输出结果
tensor([[1, 2]])
tensor([[1],
        [2],
        [3]])
tensor([[2, 3],
        [3, 4],
        [4, 5]])

自动求导(autograd)

PyTorch 中,所有神经网络的核心是 autograd 包。autograd包为张量上的所有操作提供了自动求导机制。它是一个在运行时定义 ( define-by-run )的框架,这意味着反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。

#torch.Tensor类
#torch.Tensor 是这个包的核心类。如果设置它的属性 .requires_grad 为 True,那么它将会追踪对于该张量的所有操作。
.requires_grad=True/False
#如果 y 是标量,则不需要为 backward() 传入任何参数;否则,需要传入一个与 y 同形的Tensor
.backward()
#当完成计算后可以通过调用 .backward(),来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad属性。
.grad()
#要阻止一个张量被跟踪历史,可以调用.detach()方法将其与计算历史分离,并阻止它未来的计算记录被跟踪。
.detach()
#为了防止跟踪历史记录(和使用内存),可以将代码块包装在 with torch.no_grad(): 中。在评估模型时特别有用,因为模型可能具有 requires_grad = True 的可训练的参数,但是我们不需要在此过程中对他们进行梯度计算。
with torch.no_grad():

#Function类
#Tensor 和 Function 互相连接生成了一个无环图 (acyclic graph),它编码了完整的计算历史。每个张量都有一个.grad_fn属性,该属性引用了创建 Tensor 自身的Function(除非这个张量是用户手动创建的,即这个张量的grad_fn是 None )。它记录的是tensor的运算信息,比如c=a+b,那么c.grad_fn=<AddBackward0>,记录grad_fn信息的意义有利于我们使用反向传播算法,由子tensor计算父tensor的梯度。
.grad_fn

梯度

with torch.no_grad()

(23条消息) 【pytorch系列】 with torch.no_grad():用法详解_大黑山修道的博客-CSDN博客_torch.no_grad():

#grad在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。

#如果我们想要修改 tensor 的数值,但是又不希望被 autograd 记录(即不会影响反向传播), 那么我们可以对 tensor.data 进行操作。
.data

torch.autograd 这个包就是用来计算一些雅可比矩阵的乘积

当输入(x)是向量,输出(y)是标量时,在x上的梯度是一个向量,这时不需要gradient参数。 当输入(x)是向量,输出(y)是向量时,y在x上的梯度是一个雅可比矩阵。torch.autograd不能直接计算完整的雅可比矩阵,但是如果我们只想要雅可比向量积,只需将这个向量(gradient)作为参数传给 backward()。

img

雅可比向量积的解释(理解的重点)

详解Pytorch 自动微分里的(vector-Jacobian product) - 知乎 (zhihu.com)

并行计算

在利用PyTorch做深度学习的过程中,可能会遇到数据量较大无法在单块GPU上完成,或者需要提升计算速度的场景,这时就需要用到并行计算,可以充分利用GPU的性能,让多个GPU来参与训练

CUDA

CUDA是我们使用GPU的提供商——NVIDIA提供的GPU并行计算框架。对于GPU本身的编程,使用的是CUDA语言来实现的。但是,在我们使用PyTorch编写深度学习代码时,使用的CUDA又是另一个意思。在PyTorch使用 CUDA表示要开始要求我们的模型或者数据开始使用GPU了。

在编写程序中,当我们使用了 .cuda() 时,其功能是让我们的模型或者数据从CPU迁移到GPU(0)当中,通过GPU开始计算

Tips:

  1. 我们使用GPU时使用的是.cuda()而不是使用.gpu()。这是因为当前GPU的编程接口采用CUDA,但是市面上的GPU并不是都支持CUDA,只有部分NVIDIA的GPU才支持,AMD的GPU编程接口采用的是OpenCL,在现阶段PyTorch并不支持。
  2. 数据在GPU和CPU之间进行传递时会比较耗时,我们应当尽量避免数据的切换
  3. GPU运算很快,但是在使用简单的操作时,我们应该尽量使用CPU去完成。
  4. 当我们的服务器上有多个GPU,我们应该指明我们使用的GPU是哪一块,如果我们不设置的话,tensor.cuda()方法会默认将tensor保存到第一块GPU上,等价于tensor.cuda(0),这将会导致爆出out of memory的错误。我们可以通过以下两种方式继续设置。

常见方法

Network partitioning

将一个模型的各个部分拆分,然后将不同的部分放入到GPU来做不同任务的计算

Layer-wise partitioning

同一层的模型做一个拆分,让不同的GPU去训练同一层模型的部分任务

问题:不同模型组件在不同的GPU上时,GPU之间的传输就很重要,对于GPU之间的通信是一个考验。但是GPU的通信在这种密集任务中很难办到,所以这个方式慢慢淡出了视野。所以前两种方式并不常用

Data parallelism

不再拆分模型,我训练的时候模型都是一整个模型。但是我将输入的数据拆分

主流方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值