文章目录
一、Pytorch张量及基本数据类型
二、张量的创建
1.通过torch.tensor()方法创建张量,可通过多种形式创建,如下:
2.生成随机矩阵
三、张量运算
1.张量Tensor是Pytorch最基本的操作对象,它表示一个多维矩阵。标量可以称为0维张量,向量可以称为1维张量,矩阵可以称为2维张量,RGB图像可以表示3维张量。张量类似于Numpy的数组,但张量可以在GPU上使用以加速计算。
2.dtype:张量的数据类型,如torch.FloatTensor。Pytorch提供了9种数据类型,共分为3大类:float(16-bit, 32-bit, 64-bit)、integer(unsigned-8-bit, 8-bit, 16-bit, 32-bit, 64-bit)、Boolean。模型参数和数据用的最多类型是float-32-bit。labell常用的类型是integer-64-bit。
Date type | dtype |
32-bit floating point | torch.float32/torch.float |
64-bit floating point | torch.float64/torch.double |
16-bit floating point | torch.float16/torch.half |
8-bit integer(unsigned) | torch.uint8 |
8-bit integer(signed) | torch.int8 |
16-bit integer(signed) | torch.int16/torch.short |
32-bit integer(signed) | torch.int32/torch.int |
64-bit integer(signed) | torch.int64/torch.long |
Boolean | torch.bool |
3.张量的类型转换
#浮点型和整数型的隐式转化
torch.tensor([1.1, 2]).dtype
结果为:torch.float32
#布尔型和数值型的隐式转化
torch.tensor([True, 2.0])
结果为:tensor([1., 2.])
t = torch.tensor(np.array([1, 2]))
print(t)
结果为:tensor([1,2])
#转化为默认浮点型
t.float()
结果为:tensor([1., 2.])
#转化为双精度浮点型
t.double()
结果为:tensor([1., 2.], dtype=torch.float64)
#并不改变张量的原始类型
t.dtype
结果为:torch.int64
#转化为16位整数型
t.short()
结果为:tensor([1, 2], dtype=torch.int16)
(1)通过列表创建
t = torch.tensor([1, 2])
(2)通过元组创建
t = torch.tensor((1, 2))
(3)通过numpy数组创建
import numpy as np
a = np.array((1, 2)) #a是一个numpy多维数组
t = torch.tensor(a)
在使用torch.tensor()方法创建张量时会发生数据的复制行为。
代码如下(示例):
import torch
#0-1之间均匀分布随机数,2行3列数组
x = torch.rand(2, 3)
print(x)
#0-1之间正态分布随机数,3行4列数组
y = torch.randn(3, 4)
print(y)
#全0数组
z = torch.zeros(2, 3)
print(z)
#全1数组,三维数组,可以理解为两个3*4的矩阵
q = torch.ones(2, 3, 4)
print(q)
三、张量运算
索引切片
表达式的意义是,从start开始到end结束,每隔step个进行采样。通过[start:end]形式索引,这种方式是左闭右开的方式[start:end),左边默认是从0开始索引。注意负值的索引即表示倒数第几个元素,例如-2就是倒数第二个元素。代码如下(示例):
t = torch.randint(1, 10, [3, 3])
print(t)
结果为:tensor([[8, 2, 9],
[2, 5, 9],
[3, 9, 9]])
#第一行数据
t[0]
结果为:tensor([8, 2, 9])
#第三行第三列数据
t[2][2]
结果为:tensor(9)
#第一行至第三行,全部列
t[0:3, :]
结果为:tensor([[8, 2, 9],
[2, 5, 9],
[3, 9, 9]])
#第一行至第二行
t[0:2, :]
结果为:tensor([[8, 2, 9],
[2, 5, 9]])
#第二行至最后行,最后一列
t[1: , -1]
结果为:tensor([9, 9])
#第一行至最后行,第0列到最后一列每隔两列取一列
t[1: , : : 2]
结果为:tensor([[2, 9],
[3, 9]])
gather函数定义如下:torch.gather(input, dim, index, *, sparse_grad=False, out=None) -> Tensor
输入input和索引index具有相同数量的维度,即input.shape = index.shape。对于任意维数,只要d != dim, index.size(d) <= input.size(d),即对于可以不用索引维数d上的全部数据。输出out和索引index具有相同的形状。输入和索引不会相互广播。
gather是通过将索引在指定维度dim上的值替换为index的值,但是其他维度索引不变的情况下获取tensor数据。直观上可以理解为对矩阵进行重排,比如对每一行(dim=1)的元素进行变换,比如torch.gather(a, 1, torch.tensor([[1, 2, 0], [1, 2, 0]]))的作用就是对矩阵a每一行的元素,进行permtute(1, 2, 0)操作。
torch.index_select函数作用是返回沿着输入张量的指定维度的指定索引号进行索引的张量子集。函数定义如下:torch.index_select(input, dim, index, *, out=None) -> Tensor
函数返回一个新的张量,它使用数据类型为LongTensor的index中的条目沿维度dim索引输入张量。返回的张量具有与原始张量(输入)相同的维数。维度尺寸与索引长度相同,其他尺寸与原始张量中的尺寸相同。代码如下(示例):
x = torch.randn(3, 4)
x
tensor([[0.1427, 0.0231, -0.5414, -1.0009],
[-0.4664, 0.2647, -0.1228, -1.1068],
[-1.1734, -0.6571, 0.7230, -0.6004]])
indices = torch.tensor([0, 2])
torch.index_select(x, 0, indices)
tensor([[0.1427, 0.0231, -0.5414, -1.0009],
[-1.1734, -0.6571, 0.7230, -0.6004]])
torch.index_select(x, 1, indices)
tensor([[0.1427, -0.5414],
[-0.4664, -0.1228],
[-1.1734, 0.7230]])
2.合并分割
>>> a = torch.arange(0,9).view(3,3)
>>> b = torch.arange(10,19).view(3,3)
>>> c = torch.arange(20,29).view(3,3)
>>> cat_abc = torch.cat([a,b,c], dim=0)
>>> print(cat_abc.shape)
torch.Size([9, 3])
>>> print(cat_abc)
tensor([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[10, 11, 12],
[13, 14, 15],
[16, 17, 18],
[20, 21, 22],
[23, 24, 25],
[26, 27, 28]])
>>> stack_abc = torch.stack([a,b,c], axis=0) # torch中dim和axis参数名可以混用
>>> print(stack_abc.shape)
torch.Size([3, 3, 3])
>>> print(stack_abc)
tensor([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[10, 11, 12],
[13, 14, 15],
[16, 17, 18]],
[[20, 21, 22],
[23, 24, 25],
[26, 27, 28]]])
>>> chunk_abc = torch.chunk(cat_abc, 3, dim=0)
>>> chunk_abc
(tensor([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]),
tensor([[10, 11, 12],
[13, 14, 15],
[16, 17, 18]]),
tensor([[20, 21, 22],
[23, 24, 25],
[26, 27, 28]]))
torch.split和torch.chunk。torch.split()和torch.chunk()可以看作是torch.cat()的逆运算。split()作用是将张量拆分为多个块,每个块都是原始张量的视图。chunk()作用是将tensor按dim(行或列)分割成chunks个tensor块,返回的是一个元组。split()和chunk()函数的定义如下:torch.split(tensor, split_size_or_sections, dim=0); torch.chunk(input, chunks, dim=0)。代码如下(示例):
>>> a = torch.arange(10).reshape(5,2)
>>> a
tensor([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
>>> torch.split(a, 2)
(tensor([[0, 1],
[2, 3]]),
tensor([[4, 5],
[6, 7]]),
tensor([[8, 9]]))
>>> torch.split(a, [1,4])
(tensor([[0, 1]]),
tensor([[2, 3],
[4, 5],
[6, 7],
[8, 9]]))
>>> torch.chunk(a, 2, dim=1)
(tensor([[0],
[2],
[4],
[6],
[8]]),
tensor([[1],
[3],
[5],
[7],
[9]]))
3.维度变换
3.1、squeeze\unsqueeze维度增减
#squeeze用例
a = torch.rand(1, 1, 3, 3)
b = torch.squeeze(a)
c = a.squeeze(1)
print(b.shape)
torch.Size([3, 3])
print(c.shape)
torch.Size([1, 3, 3])
#unsqueeze用例
x = torch.rand(3, 3)
y1 = torch.unsqueeze(x, 0)
y2 = x.unsqueeze(0)
print(y1.shape)
torch.Size([1, 3, 3])
print(y2.shape)
torch.Size([1, 3, 3])
3.2、transpose\permute 维度交换
import torch
input = torch.rand(1,3,28,32) # torch.Size([1, 3, 28, 32]
print(b.transpose(1, 3).shape) # torch.Size([1, 32, 28, 3])
print(b.transpose(1, 3).transpose(1, 2).shape) # torch.Size([1, 28, 32, 3])
print(b.permute(0,2,3,1).shape) # torch.Size([1, 28, 32, 3]