张量
0维张量:标量
1维张量:向量
2维张量:矩阵
3维张量:时间序列数据、单张彩色图片、股价、文本数据
一个图像:(width, height, channel) = 3D
处理多张图像:(batch_size, width, height, channel) = 4D
在pytorch中,torch.Tensor是存储和变换数据的主要工具,Tensor提供了GPU计算和自动求梯度的功能,所以更加适合深度学习
如何创建tensor
- 构建随机化初始矩阵,torch.rand()
import torch
x=torch.rand(4,3)
print(x)
- 构建全0矩阵,torch.zeros(),通过dtype设置数据类型为long
(可以利用torch.zero_()和torch.zeros_like()将现有矩阵转换为全0矩阵)
import torch
x=torch.zeros(4,3,dtype=long)
print(x)
- 使用torch.tensor()直接使用数据,构造一个张量
import torch
x=torch.tensor([5.5,3])
print(x)
- 基于已经存在的tensor,创建一个tensor
x=x.new_ones(4,3,dtype=torch.double)
#创建一个新的全1的矩阵tensor,返回的tensor默认具有相同的torch.dtype和torch.device
# 也可以像之前的写法 x=torch.ones(4,3,dtype=torch.double)
print(x)
x=torch.rands_like(x,dtype=torch.float)
#重置数据类型
print(x)
#结果会有一样的size
#获取它的维度信息
print(x.size())
print(x.shape)
- 创建tensor,用dtype指定类型
?torch.tensor
a=torch.tensor(1.0,dtype=torch.float)
b=torch.tensor(1,dtype=torch.long)
c=torch.tensor(1.0,dtype=torch.int8) #注意类型要匹配
print(a,b,c)
- 使用指定类型函数随机初始化指定大小的tensor
d=torch.FloatTensor(2,3)
e=torch.IntTensor(2) #没有指定数据结构
f=torch.IntTensor([1,2,3,4]) #对于已经定义好的数据结构可以直接转换
print(d,'\n',e,'\n',f)
- tensor和numpy array之间的相互转换
import numpy as np
g=np.array([[1,2,3],[4,5,6]])
h=torch.tensor(g) #从array转换为tensor
print(h)
i=torch.from_numpy(g)
print(i)
j=h.numpy() ##从tensor转换为array
print(j)
- 常见的构造tensor函数
k=torch.rand(2,2)
l=torch.ones(2,3)
m=torch.zeros(2,3)
n=torch.arange(0,10,2) #从0到10,步长为2
print(k,'\n',l,'\n',m,'\n',n)
- 查看tensor的维度信息
print(k.shape)
print(k.size())
张量的操作
- 加法操作
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) #直接在y上修改
- 索引操作
索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改;如果不想修改,可以考虑使用copy()
import torch
x=torch.rand(4,3)
#取第二列
print(x[:,1])
#取第一行
y=x[0,:]
y+=1
print(y)
print(x[0,:]) #源Tensor的第一行也被修改了
- 维度变换(张量进行维度变换有torch.view()和torch.reshape())
- torch.view()
x=torch.randn(4,4)
y=x.view(16)
z=x.view(-1,8) #-1是指这一维的维数由其他维度决定
print(x.size(),y.size(),z.size())
x+=1
print(x)
print(y) #y也会跟着一起+1
torch.view()返回的新tensor与原tensor共享内存,改变一个另一个也会跟着改变(view()只是改变了对这个张量的观察角度)
- torch.reshape()
如果希望原始张量与变换后的张量互不影响,即他们不共享内存,需要使用第二种方法torch.reshape(),可以改变张量的形状,但是函数不能保证返回的是拷贝值,所以不推荐使用。推荐的方法是我们先用clone()创建一个张量副本然后再使用torch.view()进行函数维度变换。
clone()还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源tensor。
- 取值操作
用tensor.item()获得这个value,而不获得其它性质
import torch
x=torch.randn(1)
print(type(x)) #tensor
print(type(x.item())) #float
广播机制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的维度:squeeze
o=torch.rand(2,3)
print(o)
r=o.unsqueeze(1) #在第二个上增加一维
print(r)
print(r.shape)
s=r.squeeze(0) #squeeze只能对1维进行操作,如果这一维不是1就不能进行操作,第0维不是1,所以不能进行操作
print(s)
print(s.shape)
#以下是正确的操作
t=r.squeeze(1)
print(t)
print(t.shape)
自动求导
(autograd包为张量提供了自动求导机制,因此反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的)
torch.Tensor是autograd包的核心类,对属性.requires_grad设置为True,它会追踪该张量的所有操作。当完成计算后可以通过调用.backward()来计算所有的梯度,这个张量的所有梯度将会自动累加到.grad属性。
grad在反向传播中是累加的,意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前把梯度清零
通过y=x1+2*x2说明自动求导
import torch
x1=torch.tensor(1.0,requires_grad=True)
x2=torch.tensor(2.0,requires_grad=True)
y=x1+2*x2
print(y)
#查看每个变量是否需要求导
print(x1.requires_grad)
print(x2.requires_grad)
print(y.requires_grad)
#查看每个变量导数大小,此时因为还没有反向传播,导数都不存在
print(x1.grad.data)
print(x2.grad.data)
print(y.grad.data)
x1
#反向传播后看导数大小
y=x1+2*x2
y.backward()
print(x1.grad.data)
print(x2.grad.data)
#导数是会累积的,重复运行相同命令,grad会增加
y=x1+2*x2
y.backward()
print(x1.grad.data)
print(x2.grad.data)
#每次计算前需要清除当前导数值避免累积,可以通过pytorch的optimizer实现
#如果不允许求导,会出现什么情况??会报错
x1=torch.tensor(1.0,requires_grad=False)
x2=torch.tensor(2.0,requires_grad=False)
y=x1+2*x2
y.backward()
####并行计算
数据量较大无法在单块GPU上完成,或者需要提升计算速度
**在编写完模型之后,让多个GPU来参与训练,减少训练时间**
####CUDA
在程序中使用.cuda(),是让我们的模型或者数据从CPU迁移到GPU(0)当中
当我们的服务器上有多个GPU,我们应该指明我们使用的GPU是哪一块,如果我们不设置的话,tensor.cuda()方法会默认将tensor保存到第一块GPU上,等价于tensor.cuda(0),这将会导致爆出out of memory的错误。我们可以通过以下两种方式继续设置:
设置在文件最开始部分
import os
os.environ["CUDA_VISIBLE_DEVICE"] = "2" # 设置默认的显卡
CUDA_VISBLE_DEVICE=0,1 python train.py # 使用0,1两块GPU
最常用的是不同数据分布到不同的GPU中
####cuDNN
cuDNN适用于深度神经网络的加速库