一起来学PyTorch——PyTorch基础

本文介绍了PyTorch中的基本操作对象Tensor,包括其与Numpy的相似性、数据类型的选择、创建方法、维度查看、组合与分块的操作,以及索引、变形等基本操作。此外,还提到了Tensor的数学运算和归并操作。
摘要由CSDN通过智能技术生成

大家好,今天开始想整理一下PyTorch的内容,开始的基础知识可能更像书上写得内容,没有什么个人的理解。希望各位同学、同行们可以一起交流,随着更新的进行之后也会逐渐加入个人的理解。欢迎大家共同探讨。

基本数据(Tensor)

Tensor,我们称作张量,是PyTorch中的基本操作对象,实际上就是一个多维数组。从使用的角度来看,Tensor和Numpy中的ndarrays非常类似,相互之间也可以互相转换。

  1. Tensor数据类型

在使用时,Tensor可以有不同的数据类型,官方给出了7种CPU类型和8种GPU类型,在使用时可以根据网络模型所需要的精度与显存容量,合理的进行选取

PyTorch可以使用set_default_tensor_type函数设置使用的Tensor类型。

# 使用上表中的64位浮点类型(torch.DoubleTensor)
torch.set_default_tesor_type('torch.DoubleTensor')

对于Tensor之间的类型转换,可以通过type(new_type)、type_as()、int()等多种方式进行操作,尤其是type_as()函数,最为常用。

#创建新Tensor,默认类型为torch.FloatTensor
>>> a = torch.Tensor([[1, 2], [3, 4])
>>> a 
tensor([[1, 2],
        [3, 4]])

# 使用int(), float(), double()等直接进行数据类型的转换
>>> b = a.double()
>>> b
tensor([[1, 2],
        [3, 4]], dtype=torch.float64)

# 使用type()函数
>>> c = a.type(torch.DoubleTensor)
>>> c
tensor([[1, 2],
        [3, 4]], dtype=torch.float64)

#使用type_as()函数
>>> d = a.type_as(b)
>>> d
tensor([[1, 2],
        [3, 4]], dtype=torch.float64)

  1. Tensor的创建与维度查看

Tensor有多种创建方法,如基础的构造函数Tensor(),还有多种与Numpy十分相似的方法,如ones(), eye(), zeros()和randn()等。

#最基础的Tensor()函数创建方法,参数为Tensor的每一维的大小
a = torch.Tensor(2, 2)

# 使用Python的list进行创建
b = torch.Tensor([[1, 2], [3, 4]])

# 使用zeros(), ones()创建
c = torch.zeros(2, 2)
d = torch.ones(2, 2)

# 使用eye()函数,对角线元素为1, 不要求行列数相同,生成二维矩阵
e = torch.eye(2, 2)

# 使用arange(start, end, step)函数,表示从start到end, 间距为step,一维向量。
f = torch.arange(1, 6, 2) #f为 tensor([1, 3, 5])

# 使用linspace(start, end, steps)函数,表示从start到end,一共steps份,一维向量。
g = torch.linspace(1, 6, 2) # g为tensor([1, 6])

# 使用randperm(num)函数,生成长度为num的随机排列向量
h = torch.randperm(4)

对于Tensor的维度,可以使用Tensor.shape()或者Tensor.size()查看每一维的大小。

对于Tensor的元素总个数,可以使用Tensor.numel()或者Tensor.nelement()查看。

  1. Tensor的组合与分块

组合与分块是将Tensor相互叠加或者分开,是十分常用的两个功能,Pytorch提供了多种操作函数。

组合中的torch.cat()函数,是指沿着已有的数据的某一维度进行拼接,操作后,数据的总维度不变。而且在进行拼接时,其他维度必须相同。而tensor.stack()函数将新增维度。

#创建两个 2*2 的Tensor
>>> a = torch.Tensor([1, 2], [3, 4])
>>> b = torch.Tensor([5, 6], [7, 8])

# 以第一维进行拼接,则变成 4*2 的矩阵
>>> torch.cat([a, b], 0)
tensor([[1, 2],
        [3, 4],
        [5, 6],
        [7, 8]])

# 以第二维进行拼接,则变成 2*4 的矩阵
>>> torch.cat([a, b], 1)
tensor([[1, 2, 5, 6],
        [3, 4, 7, 8]])

# 以第0维进行stack,叠加的基本单位为序列本身,即a与b,输出[a, b], 维度为2*2*2
>>> torch.stack([a, b], 0)
tensor([
        [[1, 2], 
         [3, 4]],
        [[5, 6],
         [7, 8]]
                ])

# 以第1维进行stack,叠加的基本单位为每一行,输出2*2*2
>>> torch.stack([a, b], 1)
tensor([
        [[1, 2],
         [5, 6]],
        [[3, 4],
         [7, 8]]
                ])

#以第2维进行stack,叠加的基本单位为每一行的每一个元素,输出2*2*2
>>> torch.stack([a, b], 2)
tensor([[[1, 5],
         [2, 6]],
        [[3, 7],
         [4, 8]]
                ])

分块是将Tensor分割成不同的子Tensor,主要有torch.chunk()与torch.split()两个函数。chunk函数需要指定分块的数量,而split函数需要指定每一块的大小。

>>> a = torch.Tensor([[1, 2, 3],  [4, 5, 6]])
>># 使用chunk,沿着第-0维进行分块,一共分两块,因此分割成两个1 1*3的的 的Tensor
>>> trochorch.chunk(a, 2, 0)
(tensor[([[1, 2, 3]]), tensor([4, 5, 6]])

# 沿着第1维进行分块,因此分割成两个Tensor,当不能整除时,最后一个的维数会小于前面的
# 因此第一个Tensor为 2*2,第二个为2*1
>>> torch.chunk(a, 2, 1)
(tensor([[1, 2], [4, 5]]), tensor([[3,], [6,]])

# 使用split,沿着第0维分块,每一块维度为2,由于第一维维度总共为2,因此相当于没有分割
>>> torch.split(a, 2, 0)
(tensor([[1, 2, 3], [4, 5, 6]]), )

# 沿着第1维分块,每一块维度为2,因此第一个Tensor为2*2,第二个为2*1
>>> torch.split(a, 2, 1)
(tensor([[1, 2], [4, 5]]), tensor([[3, ], [6, ], ]))

# split也可以根据输入的list进行自动分块,list中的元素代表了每一个快占的维度
>>> torch.split(a, [1, 2], 1)
(tensor([[1, ],[4, ]]), tensor([[2, 3], [5, 6]]) )
  1. Tensor的索引与变形

Tensor的索引操作和numpy非常相似,主要包括下标索引、表达式索引、使用torch.where(),Tensor.clamp()的选择性索引。

>>> a = torch.Tensor([[0,1], [2, 3]])
>>> a
tensor([[ 0., 1.], [ 2., 3.]])

# 根据下标进行索引
>>> a[1]
tensor([ 2., 3.])
>>> a[0,1]
tensor(1.)

# 选择a中大于0的元素,返回和a相同大小的Tensor,符合条件的置1,否则置0
>>> a>0
tensor([[ 0, 1],
[ 1, 1]], dtype=torch.uint8)

# 选择符合条件的元素并返回,等价于torch.masked_select(a, a>0)
>>> a[a>0]
tensor([ 1., 2., 3.])

# 选择非0元素的坐标,并返回
>>> torch.nonzero(a)
tensor([[ 0, 1],
[ 1, 0],
[ 1, 1]])

# torch.where(condition, x, y),满足condition的位置输出x,否则输出y
>>> torch.where(a>1, torch.full_like(a, 1), a)
tensor([[ 0., 1.],
[ 1, 1.]])

# 对Tensor元素进行限制可以使用clamp()函数,示例如下,限制最小值为1,最大值为2
>>> a.clamp(1,2)
tensor([[ 1., 1.],
[ 2., 2.]])

变形操作是指改变Tensor的维度,以适应在深度学习的计算中,数据维度经常变换的需求,是一种非常重要的基本操作。

  • view(), resize(), reshape()

在不改变Tensor数据的前提下任意改变Tensor的形状,必须保证调整前后的元素总数相同。

>>> a=torch.arange(1,5)
>>> a
tensor([ 1., 2., 3., 4.])
# 分别使用view()、resize()及reshape()函数进行维度变换
>>> b=a.view(2,2)
>>> b
tensor([[ 1., 2.],
[ 3., 4.]])
>>> c=a.resize(4,1)
>>> c
tensor([[ 1.],
[ 0.],
[ 0.],
[ 4.]])
>>> d=a.reshape(4,1)
>>> d
tensor([[ 1.],
[ 0.],
[ 0.],
[ 4.]])
# 改变了b、c、d的一个元素,a也跟着改变了,说明两者共享内存
>>> b[0,0]=0
>>> c[1,0]=0
>>> d[2,0]=0
>>> a
tensor([ 0., 0., 0., 4.])
  • transpose(), permute() 函数

transpose()函数可以将指定的两个维度的元素进行转置,而permute()函数可以按照给定的维度进行维度变换。

>>> a=torch.randn(2,2,2)
>>> a
tensor([[[-0.9268, 0.6006],
[ 1.0213, 0.5328]],
[[-0.7024, 0.7978],
[ 1.0553, -0.6524]]])

# 将第0维和第1维的元素进行转置
>>> a.transpose(0,1)
tensor([[[-0.9268, 0.6006],
[-0.7024, 0.7978]],
[[ 1.0213, 0.5328],
[ 1.0553, -0.6524]]])

# 按照第2、1、0的维度顺序重新进行元素排列
>>> a.permute(2,1,0)
tensor([[[-0.9268, -0.7024],
[ 1.0213, 1.0553]],
[[ 0.6006, 0.7978],
[ 0.5328, -0.6524]]])
  • squeeze(), unsqueeze()函数

在实际的应用中,经常需要增加或减少Tensor的维度,尤其是维度 为1的情况,这时候可以使用squeeze()与unsqueeze()函数,前者用于去除 size为1的维度,而后者则是将指定的维度的size变为1。

>>> a=torch.arange(1,4)
>>> a.shape
torch.Size([3])
# 将第0维变为1,因此总的维度为1、3
>>> a.unsqueeze(0).shape
torch.Size([1, 3])
# 第0维如果是1,则去掉该维度,如果不是1则不起任何作用
>>> a.unsqueeze(0).squeeze(0).shape
torch.Size([3])
  • expand(), expand_as() 函数

有时需要采用复制元素的形式来扩展Tensor的维度,这时expand就 派上用场了。expand()函数将size为1的维度复制扩展为指定大小,也可 以使用expand_as()函数指定为示例Tensor的维度。

>>> a=torch.randn(2,2,1)
>>> a
tensor([[[ 0.5379],
[-0.6294]],
[[ 0.7006],
[ 1.2900]]])
# 将第2维的维度由1变为3,则复制该维的元素,并扩展为3
>>> a.expand(2,2,3)
tensor([[[ 0.5379, 0.5379, 0.5379],
[-0.6294, -0.6294, -0.6294]],
[[ 0.7006, 0.7006, 0.7006],
[ 1.2900, 1.2900, 1.2900]]])
  1. Tensor的排序与取极值

比较重要的是排序函数sort(),选择沿着指定维度进行排序,返回排 序后的Tensor及对应的索引位置。max()与min()函数则是沿着指定维度 选择最大与最小元素,返回该元素及对应的索引位置

>>> a=torch.randn(3,3)
>>> a
tensor([[ 1.0179, -1.4278, -0.0456],
[-1.1668, 0.4531, -1.5196],
[-0.1498, -0.2556, -1.4915]])

# 按照第0维即按行排序,每一列进行比较,True代表降序,False代表升序
>>> a.sort(0, True)[0]
tensor([[ 1.0179, 0.4531, -0.0456],
[-0.1498, -0.2556, -1.4915],
[-1.1668, -1.4278, -1.5196]])
>>> a.sort(0, True)[1]
tensor([[ 0, 1, 0],
[ 2, 2, 2],
[ 1, 0, 1]])

# 按照第0维即按行选取最大值,即将每一列的最大值选取出来
>>> a.max(0)
(tensor([ 1.0179, 0.4531, -0.0456]), tensor([ 0, 1, 0]))

对于Tensor的单元素数学运算,如abs()、sqrt()、log()、pow()和三 角函数等,都是逐元素操作(element-wise),输出的Tensor形状与原始 Tensor形状一致。

对于类似求和、求均值、求方差、求距离等需要多个元素完成的操 作,往往需要沿着某个维度进行计算,在Tensor中属于归并操作,输出 形状小于输入形状。牢记!!与numpy很相似。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值