加油加油加油
2.2数据操作
torch.tensor是存储和变换数据的主要工具,tonsor和numpy非常类似,但是tensor提供GPU计算和自动求梯度等更多功能,这使得tensor更加适合深度学习;
tensor可翻译为张量;
1.创建tensor
import torch# 引入torch包;
x=torch.empty(5,3)#创建5*3的未初始化的数组;
print(x);#输出结果全0;
x=torch.rand(5,3)#创建5*3的随机初始化的数组;
print(x)
x=torch.zeros(5,3,dtype=torch.long)#创建5*3的值全部为0的数组;
print(x)
x=torch.tensor([5.5,3])#直接输入数据创建tensor;
print(x)
x=torch.rand_like(x,dtype=torch.float)#为x指定新的数据类型;
print(x)
x=torch.arange(1,3)#创建一个数组,数组中的前两个元素是1,2
print(x)
a=torch.linspace(1,12,12).view(3,4)
# linspace(x,y,n)从x到y生成n个点,间距为(y-x)/n;
2.获取tensor的形状
print(x.size())#获取数组x的数据类型;
print(x.shape)#获取数组x的数据类型;
3.tensor的操作
介绍tensor的各种操作
加法形式1:
y=torch.rand(5,3)
print(y)
print(x+y)
加法形式2:
print(torch.add(x,y))
加法形式3——指定输出
result=torch.empty(5,3)
print(result)
torch.add(x,y,out=result)
print(result)
加法形式4——将x加到y上
y.add_(x)
print(y)
4.索引
注意:索引出来的结果与原数据共享内存,也即修改一个另一个也随着改变;
x=torch.rand(5,3)
print(x)
y=x[0,:]
y+=1
print(y)
运行结果:
tensor([[0.0877, 0.1335, 0.2482],
[0.8710, 0.8541, 0.6168],
[0.2556, 0.0903, 0.0240],
[0.9340, 0.2565, 0.4446],
[0.3407, 0.6186, 0.1206]])
tensor([1.0877, 1.1335, 1.2482])
tensor([[1.0877, 1.1335, 1.2482],
[0.8710, 0.8541, 0.6168],
[0.2556, 0.0903, 0.0240],
[0.9340, 0.2565, 0.4446],
[0.3407, 0.6186, 0.1206]])
5.改变tensor形状
view()函数来改变tensor的形状:
view()返回的向量与原向量内存共享,也即改变一个向量,另一个向量也随即改变;
若不想共享内存(返回一个真正的副本),我们可以先用clone()创造一个副本;
x=torch.rand(5,3)
y=x.view(15)#展开成列向量
z=y.view(-1,5)#展开成有5列的向量;
print(y.size())
print(z.size())
输出结果:
torch.Size([15])
torch.Size([3, 5])
非共享内存
x=torch.rand(5,3)
x_cp=x.clone().view(15)
x-=1;
print(x.size())
print(x_cp.size())
输出结果:
torch.Size([5, 3])
torch.Size([15])
item():将一个标量tensor转换为一个python number:
x=torch.rand(1)
print(x)
print(x.item())
输出结果:
tensor([0.6806])
0.680623471736908
常见的线性函数:
求矩阵的迹,对角线元素之和,逆矩阵,上三角,下三角,转置,矩阵的乘法,
x=torch.rand(3,3)
print(x)
print(x.trace())#求矩阵的迹(对角线元素之和);
print(x.diag())#对角线元素之和;
print(x.inverse())#求矩阵的逆;
print(x.triu())#求矩阵的上三角
print(x.tril())#求矩阵的下三角;
print(x.t())#矩阵的转置;
y=torch.rand(3,1)
print(x.mm(y))#矩阵乘法;
输出结果:
tensor([[0.1231, 0.4921, 0.6451],
[0.6558, 0.6020, 0.9982],
[0.8589, 0.6410, 0.1479]])
tensor([[0.4106],
[0.1925],
[0.8080]])
tensor(0.8731)
tensor([0.1231, 0.6020, 0.1479])
tensor([[-2.2579, 1.3966, 0.4216],
[ 3.1170, -2.1966, 1.2303],
[-0.3965, 1.4090, -1.0189]])
tensor([[0.1231, 0.4921, 0.6451],
[0.0000, 0.6020, 0.9982],
[0.0000, 0.0000, 0.1479]])
tensor([[0.1231, 0.0000, 0.0000],
[0.6558, 0.6020, 0.0000],
[0.8589, 0.6410, 0.1479]])
tensor([[0.1231, 0.6558, 0.8589],
[0.4921, 0.6020, 0.6410],
[0.6451, 0.9982, 0.1479]])
tensor([[0.6665],
[1.1917],
[0.5956]])
6.广播机制
当对形状不同的tensor按元素运算时,可能会触发广播机制,先适当复制元素使这两个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]])
分析:x和y分别是1行3列和3行1列的元素,计算x+y时,x第一行的两个元素被广播到了第2和第3行;y第1列的元素被广播到了第2列;如此就对2个3行2列的元素进行相加;
7. 运算的内存开销
索引,view是不会开辟新内存,而y=x+y这样是会开辟新内存的,使用python的id()函数来证明;
x=torch.tensor([1,2])
print(x)
y=torch.tensor([2,3])
print(y)
id_ybefore=id(y)
y=y+x
print(id(y)==id_ybefore)
运行结果:
tensor([1, 2])
tensor([2, 3])
False
如果我们想指定结果到原来的内存,有两种方法,
方法1:索引来进行替换操作,如下:
z=torch.tensor([3,4])
print(z)
id_zbefore=id(z)
z[:]=z+x
print(id(z)==id_zbefore)
运行结果:
tensor([3, 4])
True
方法2: 使用全名运算符函数中的out来达到这种效果;
x=torch.tensor([1,2])
print(x)
y=torch.tensor([2,3])
print(y)
id_ybefore=id(y)
torch.add(x,y,out=y)
print(id_ybefore==id(y))
运行结果:
tensor([1, 2])
tensor([2, 3])
True
方法3:
y.add(x)
print(id_ybefore==id(y))
运行结果:
True
方法4:
y+=x
print(id_ybefore==id(y))
运行结果:
True
8.tensor和numpy的互相转换
用numpy()将tensor转换为numpy(),用torch.from_numpy()将numpy转换为tensor();
注意:两个函数所产生的numpy和tensor共享同一块内存,对其中一个改变时另一个也改变;
tensor转numpy:
x=torch.tensor([1,2,3])
y=x.numpy()
print(x, y)
y+=1
print(x,y)
运行结果:
tensor([1, 2, 3]) [1 2 3]
tensor([2, 3, 4]) [2 3 4]
numpy转tensor:
x=np.ones(5)
y=torch.from_numpy(x)
print(x,y)
y+=1
print(x,y)
运行结果:
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[2. 2. 2. 2. 2.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64
所有在CPU上的tensor都支持与numpy数组进行转换;直接用torch.tensor()将numpy转换完成tensor的方法,不再与以前的数据共享内存;
x=np.ones(5)
y=torch.tensor(x)
print(x,y)
y+=1
print(x,y)
运行结果:
[1. 1. 1. 1. 1.] tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
[1. 1. 1. 1. 1.] tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
tensor ON GPU
tensor可以提供GPU计算,默认tensor是在CPU上运算,to()可以将tensor在CPU和GPU之间相互移动;
CUDA:是Nvidia推出的只能用于自家GPU的并行计算框架。只有安装这个框架才能够进行复杂的并行计算。主流的深度学习框架也都是基于CUDA进行GPU并行加速的,几乎无一例外。还有一个叫做cudnn,是针对深度卷积神经网络的加速库.
pytorch没能启动GPU。。。此地省略一万字。。。