Pytorch 基础知识
1.1 张量的概念
在PyTorch中,张量(Tensor)属于一种数据结构,它可以使一个标量、一个向量、一个矩阵,甚至是更维度的数组。类似于numpy中的数组 (ndarray),并且它们是可以相互转化的,在PyTorch中的相关计算和优化都是在Tensor的基础上完成的。
Tensor(张量)
- 标量(Scalar)是只有大小没有方向的量,如1,2,3,等
- 向量(Vector)是由大小和方向的量,如[1,2,3]
- 矩阵(Matrix)是多个向量组成的,如[[1,2,3],[4,5,6]]
- 张量是基于向量和矩阵的推广,我们可以将标量视为零阶张量,向量视为一阶张量,矩阵就是二阶张量。
- 张量是支持高效的科学计算的数组,它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)和更高维的数组(高阶数据)
- 张量(tensor)和NumPy的数组ndarray通常可以共享相同的底层内存,无需复制数据。
1.2 张量的数据类型
pytorch最基本的操作对象是Tensor(张量)
- 它表示一个多维矩阵,
- 张量类似于NumPy的ndarrays,
- 张量可以在GPU上使用以加速计算
在torch中CPU和GPU张量分别有8种数据类型,如下图所示。
注意 在pytorch种可以使用 torch.get_default_dtype()获取默认数据类型,以及使用torch.set_default_dtype()来设置默认数据类型。
常见的库文件介绍
import torch
包括了用于多维张量的数据结构,并定义了对于它们的数学计算。此外,这个包也提供了多种有效的张量及任意类型的并行化用法,以及其他有用的方法。
这个包对应于CUDA,允许用户在NVIDIA GPU(运算能力>=3.0)上运行张量计算。
import pandas as pd
是当前最流行、最常用的数据分析工具。当处理表格数据(比如存储在电子表格或数据库中的数据)时,pandas是最适合您的工具。它将帮助您探索、清理和处理您的数据。数据表被称为DataFrame,panda支持与多种文件格式或数据源的集成(csv、excel、sql、json、parquet…)。从每个数据源导入数据是由前缀为read_xx的函数提供的。类似地,to_xx方法用于存储数据……选择或过滤特定的行和或列的过滤条件下的数据。在pandas中可以使用切片、选择和提取所需数据的方法。它是基于numpy,且集成了matplotlib模块。
import numpy as np
是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix)),支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
import matplotlib.pyplot as plt
Matplotlib主要的作用,是用来生成绘图,直方图,功率谱,条形图,错误图,散点图等,而Matplotlib是一个Python的2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。
import torch
import numpy as np
(1)cpu与gpu上运算
A = torch.tensor([1,2,3])
A.device #张量在内存中
device(type='cpu')
#如果gpu可用,转到cuda上
if torch.cuda.is_available():
A = A.to('cuda')
A.device
device(type='cuda', index=0)
A = A.to('cpu')
A.device
device(type='cpu')
(2)数据类型转换
A.dtype
torch.int64
A = A.type(torch.float16)
A
tensor([1., 2., 3.], dtype=torch.float16)
A = A.long()
A.dtype
torch.int64
1.3张量的创建
(1) 使用torch.tensor()函数生成张量
##### python的列表或序列可以通过该函数构造张量
A = torch.tensor([1,2,3]) #直接从列表生成 自动判断类型 1.,2.,3. 一般使用float
A
tensor([1, 2, 3])
A.dtype
torch.int64
B = torch.FloatTensor([1,2,3]) ##用float创建
B.dtype
torch.float32
(2) 使用torch.Tensor()函数
使用torch.Tensor()函数可以生成指定形状的张量。
#根据已有的数据创建
C = torch.Tensor([1,2,3,4])
C
tensor([1., 2., 3., 4.])
#根据形参的生成特定尺寸的张量
D = torch.Tensor(2,3)
D
tensor([[0.0000, 0.0000, 0.0000],
[0.0000, 0.0000, 2.1250]])
对于指定大小,但数值特殊的一些张量也可以通过以下方式生成
torch.ones(3,3),torch.zeros(3,4),torch.empty(3,5),torch.eye(3) #单位张量
(tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]),
tensor([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]),
tensor([[9.3674e-39, 1.0745e-38, 1.0653e-38, 9.5510e-39, 1.0561e-38],
[1.0194e-38, 1.1112e-38, 1.0561e-38, 9.9184e-39, 1.0653e-38],
[4.1327e-39, 1.0194e-38, 1.0469e-38, 8.9082e-39, 1.5134e-43]]),
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]))
#指定大小的指定填充数值的张量
torch.full((3,3),fill_value=0.25)
tensor([[0.2500, 0.2500, 0.2500],
[0.2500, 0.2500, 0.2500],
[0.2500, 0.2500, 0.2500]])
针对已经生成的张量,可以使用torch.xx_like()系列函数生成与指定张量一样的张量。
#创建一个与D相同大小和类型的全1张量
torch.ones_like(D)
tensor([[1., 1., 1.],
[1., 1., 1.]])
#创建一个与D相同大小和类型的全0张量
torch.zeros_like(D)
tensor([[0., 0., 0.],
[0., 0., 0.]])
#创建一个与D相同大小和类型的随机张量
torch.rand_like(D)
tensor([[0.0310, 0.7353, 0.4987],
[0.0782, 0.7570, 0.0412]])
(3)张量和NumPy数据相互转换
一些张量可以先转化位Numpy数组,在通过Numpy数组进行相关计算后,以再次转化为张量,以方面张量的相关计算。
注意: Numpy数组转张量使用torch.as_tensor()函数或者torch.from_numpy()函数,而张量转Numpy使用torch.numpy()函数
E = np.ones((3,3))
# torch.as_tensor()
Etensor1 = torch.as_tensor(E)
# torch.from_numpy()
Etensor2 = torch.from_numpy(E)
# .numpy() 注意它是一个实例方法
E1 = Etensor1.numpy()
Etensor1,Etensor2,E1
(tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64),
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64),
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]))
(4)随机数生成张量
在Pytorch种还可以通过相关随机数来生成张量,并且可以指定生成随机数的分布函数等。在生成随机数之前,可以使用torch.manual_seed()函数,指定生成随机数的种子,用于保证随机生成的随机数是可重复出现的。
torch.manual_seed(123)
#通过mean指定随机数的均值,std参数指定随机数的标准差,如果mean和std是有多个值,可以生成多个离散正态分布中抽取的随机数。
torch.normal(mean=0.0,std=torch.arange(1,5.0))
tensor([-0.1115, 0.2407, -1.1089, -0.9617])
#在区间[0,1]上生成服从均匀分布的张量
torch.manual_seed(123)
F = torch.rand(3,4)
G = torch.randn(2,3) #创建标准分布随机数
K = torch.randn_like(G) #创建0~1之间,形状数据类似t的随机张量 在gan中常用
F,G,K
(tensor([[0.2961, 0.5166, 0.2517, 0.6886],
[0.0740, 0.8665, 0.1366, 0.1025],
[0.1841, 0.7264, 0.3153, 0.6871]]),
tensor([[-0.9724, -0.7550, 0.3239],
[-0.1085, 0.2103, -0.3908]]),
tensor([[ 0.2350, 0.6653, 0.3528],
[ 0.9728, -0.0386, -0.8861]]))
#torch.randperm(n) 将0到n中的数,随机排序后输出
torch.randperm(10)
tensor([1, 0, 6, 7, 2, 4, 5, 8, 9, 3])
(5)其它生成张量的函数
例如 torch.arange(n),torch.linspace()等间隔生成,torch.logspace()对数等间隔生成
torch.arange(start=1, end = 10, step= 5),torch.linspace(start=1, end = 10, steps= 5),torch.logspace(start=0.1, end = 1, steps= 5)
(tensor([1, 6]),
tensor([ 1.0000, 3.2500, 5.5000, 7.7500, 10.0000]),
tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000]))
1.4张量操作
(1)形状以及形状变换
A = torch.arange(12.0)
A.shape,A.reshape(3,4)
(torch.Size([12]),
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]]))
A.resize_(3,4)
tensor([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
#改变成相同尺寸
B = torch.arange(1,13)
B.resize_as_(A)
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
B.size(),B.size(0) #size与shape不同就是可以给参数,size返回某一维的大小
(torch.Size([3, 4]), 3)
(2)维度扩展
torch.unsqueeze()函数可以在张量的指定维度出入新的维度提升张量。而torch.squeeze()函数可以一处指定或者所有维度大小为1维度的张量。
C = torch.arange(12.0).reshape(2,6)
D = torch.unsqueeze(C,dim=0)
D.shape
torch.Size([1, 2, 6])
E = torch.squeeze(D)
E.shape
torch.Size([2, 6])
#expand()对张量拓展
F = E.expand(2,-1)
#repeat进行整体重复
G = E.repeat(1,2,2)
F,G
(tensor([[ 0., 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10., 11.]]),
tensor([[[ 0., 1., 2., 3., 4., 5., 0., 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10., 11., 6., 7., 8., 9., 10., 11.],
[ 0., 1., 2., 3., 4., 5., 0., 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10., 11., 6., 7., 8., 9., 10., 11.]]]))
(3)获取张量中的元素
利用切片和索引获取张量中的元素
A = torch.arange(12).reshape(1,3,4)
A
tensor([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]])
A[0]
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
#获取第0维度下的矩阵前俩行元素
A[0,0:2,:]
tensor([[0, 1, 2, 3],
[4, 5, 6, 7]])
#获取第0维度下的矩阵,最后一行-4到-1列
A[0,-1,-4:-1]
tensor([ 8, 9, 10])
根据条件刷选 torch.where()
B = -A
torch.where(A>5,A,B)#当A>5为ture时,返回A对应位置的值,否则返回B对应位置的值
tensor([[[ 0, -1, -2, -3],
[-4, -5, 6, 7],
[ 8, 9, 10, 11]]])
#获取A中大于5的元素
A[A>5]
tensor([ 6, 7, 8, 9, 10, 11])
其它函数还有troch.tril() torch.triu() torch.diag()
(4)拼接和拆分
torch.cat(),可以将多个张量在指定的维度进行拼接,得到新的张量
A = torch.arange(6.0).reshape(2,3)
B = torch.linspace(0,10,6).reshape(2,3)
#在0维度上进行拼接
C = torch.cat([A,B],dim=0)
C,C.shape
(tensor([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 0., 2., 4.],
[ 6., 8., 10.]]),
torch.Size([4, 3]))
#在1维度上连接3个张量
torch.cat((A[:,0:2],A,B),dim=1)
tensor([[ 0., 1., 0., 1., 2., 0., 2., 4.],
[ 3., 4., 3., 4., 5., 6., 8., 10.]])
torch.stack()函数,可以将多个张量按照指定的维度进行堆叠
C = torch.stack((A,B),dim=0) #注意观察与cat的不同
C.shape
torch.Size([2, 2, 3])
torch.chunk()函数可以将张量分割为特定数量的块
torch.chunk(A,2,dim=0)
(tensor([[0., 1., 2.]]), tensor([[3., 4., 5.]]))
torch.split()函数在将张量分割为特定数量的块时,可以指定每个块的大小
D1,D2,D3 = torch.split(A,[1,1,1],dim=1)
D1,D2,D3
(tensor([[0.],
[3.]]),
tensor([[1.],
[4.]]),
tensor([[2.],
[5.]]))
C = torch.stack((A,B),dim=0) #注意观察与cat的不同
C.shape
torch.Size([2, 2, 3])
torch.chunk()函数可以将张量分割为特定数量的块
torch.chunk(A,2,dim=0)
(tensor([[0., 1., 2.]]), tensor([[3., 4., 5.]]))
torch.split()函数在将张量分割为特定数量的块时,可以指定每个块的大小
D1,D2,D3 = torch.split(A,[1,1,1],dim=1)
D1,D2,D3
(tensor([[0.],
[3.]]),
tensor([[1.],
[4.]]),
tensor([[2.],
[5.]]))