首先祭上花费众多小哥哥小姐姐心血的Pytorch中文文档网址:https://blog.csdn.net/lovejay7/article/details/80315680
感觉很棒哦,大家可以动动手指到GitHub上点个Star偶~~
言归正传,这是第一次记录一个深度学习框架的博客,加上作者自己的观点和实践,认真的分析和思考,之前都是写在本子上@@
1.Tensors张量
张量是用于GPU加速的类似于Numpy中ndarray的数据结构。
from __future__ import print_funtion
import torch #我们安装的是Pytorch,在调包的时候用的是torch
第一句:
from __furture__ import print_funtion
在python3中新定义过一些基本函数的使用方法,在程序开始处加上这句话,那么即使实在python2.7的环境下,依旧要使用Python3的语法规则。
#python2
print 'a'
#python3
print('a')
还有其他的例子:
from __furture__ import division,
from __furture__ import absolute_import,
from __furture__ import with_statement
基础知识:
import torch
x = torch.Tensor(5,3)
print(x)
#结果
tensor([[-9.3959e+28, 5.7874e-43, -6.7264e+28],
[ 5.7874e-43, -9.4523e+28, 5.7874e-43],
[-6.7263e+28, 5.7874e-43, -6.7294e+28],
[ 5.7874e-43, -6.7304e+28, 5.7874e-43],
[-6.7294e+28, 5.7874e-43, -6.6958e+28]])
y = torch.rand(5,3)
print(y)
#结果
tensor([[0.6319, 0.3228, 0.6449],
[0.1274, 0.9470, 0.8020],
[0.5966, 0.5654, 0.2748],
[0.1072, 0.4547, 0.7635],
[0.2908, 0.6079, 0.4279]])
#两者的区别在于Tensor是随机的,而rand是随机归一化的
print(x.size())
print(y.size())
#结果
torch.Size([5, 3])
torch.Size([5, 3])
#torch.Size()是一个tuple(元组),它支持对元组的所有操作。
Tips:补充点小知识tuple
tuple区别于list,它是元素是不可赋值改变的,使用时,尽量使用tuple代替list,tuple不变是指指向的对象不变,对象若包含list,则list的内容是可变的,空list用[]定义,空tuple用()定义
p = ['student','php']
s = ('Java','python',p,'JS')
s[2][1]
#结果
'php'
对Tensor的运算操作,加
import torch
x = torch.Tensor(5,3)#非归一化
print(x)
y = torch.rand(5,3)#归一化
print(y)
print(x+y)#加
print(torch.add(x,y))#要有torch
result = torch.Tensor(5,3)
torch.add(x,y,out = result)#将计算结果赋值给reslut变量
print(result)
y.add_(x)#in+_place,就地操作,都带_
对Tensor的其他操作:创建
x = torch.eye(3)
x = torch.from_numpy([1,4,5,3,2,1])#返回的Tensor与ndarray共享相同的内存,Tensor不可调整大小,通过x改变的数据将反映到Tensor中。
x = torch.linspace(3,5,3)
输出:tensor([3., 4., 5.])列,起始start,结束end,steps = 3,返回一维的元素个数是steps的Tensor
x = logspace([-10,10,5])
输出:tensor([1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
x = logspace([0.1,1,5])#以10为底的幂,幂就是(1-0.1)/(5-1)=0.225为间隔,0.1,0.325,...,1
输出:tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000])
x = torch.ones(2,3)#全1 2*3矩阵
x = torch.ones(5)#全1 5*1一维矩阵
x = torch.ones_like(input)#可以模仿input的规格
x = torch.arrage(5)#以1为step,tensor([0,1,2,3,4])5是个数
x = torch.arrage(1,4)#以1为step,tensor([1,2,3,4])
x = torch.arange(1, 2.5, 0.5)#以0.5为step,tensor([1,1.5,2,2.5])返回一个floor((end−start)/step) 的一维 Tensor
对Tensor的其他操作:切片
1.#拼解
x = torch.cat((x,x,x),0)#拼接张量序列,要求被拼接的对象(N个)具有相同的结构m*n,后面一位是0则输出结果为(N*m)*n,若为1,则按列拼接,结果为m*(N*n)
2.#分割
x = torch.chunk(tensor= x, chunks= 3, dim=0)#将x在第0维方向上将张量分成3块
3.#聚合
t = torch.Tensor([[1,2],[3,4]])
a = torch.gather(t, 1, torch.LongTensor([[0,0],[1,0]]))
print(a)
输出结果是:
tensor([[1., 1.],
[4., 3.]])
4.#切片
indices = torch.LongTensor([0,1]) #指数,不能超过Tensor的范围
x= torch.randn(2,3)
t = torch.index_select(input = x,dim = 0,indices)
print(t)
输出结果是:
tensor([[-0.8068, 0.0493, 1.7335],
[ 1.3636, 0.5835, -0.4820]])
解析:当维度为0时,是选行,列数是不会缺少的
返回的张量不与原张量共享内存空间
5.#掩码取值
t = torch.randn(2,3)
print(t)
mask = t.ge(0.1) #得到一个随机的mask
print(mask)
a = masked_select(t,mask)
print(a)
得到的结果是:
tensor([[-0.2747, 1.2076, -1.4603, 0.7366],
[-0.0187, -2.4607, 1.0219, -0.0473],
[-0.7006, 1.5130, 0.0992, 0.5743]])
tensor([[0, 1, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 1]], dtype=torch.uint8)
tensor([1.2076, 0.7366, 1.0219, 1.5130, 0.5743])
总结:会生成一个0\1掩码矩阵,但矩阵是不确定的,所以结果不确定
Tips:mask与input数据的维数不一定相同,但是一定要是相同的broadcastable,
broadcastable:广播语义
(1)张量的维度至少存在,即不为空;
(2)在遍历维度大小时, 从尾部维度开始遍历, 并且二者维度必须相等, 它们其中一个要么是1要么不存在.
例子:
x=torch.FloatTensor(5,3,4,1)
y=torch.FloatTensor( 3,1,1)
这样是相同的broadcastable
6.#输出非零元素的索引
x = torch.nonzero(y)
print(x)
输出:
tensor([[0.8299, 0.5187, 0.1616],
[0.8068, 0.2404, 0.0640]])
tensor([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2]])
结论:由于数据全部非零,所以所有索引全部输出
7.分割
torch.split(x,chunk_size = 3,dim = 0)
结论:将输入张量指定维度上成相等 size 的 chunks (如果可分).
8.挤压
torch.squeeze(input = x,dim = 0)
x = torch.zeros(2,1,2,1,2)
print(x.size())
y = torch.squeeze(x)
print(y.size())
y = torch.squeeze(x, 0)
print(y.size())
y = torch.squeeze(x, 1)
print(y.size())
y = torch.squeeze(x, 2)
print(y.size())
结果:
torch.Size([2, 1, 2, 1, 2])
torch.Size([2, 2, 2])#全部
torch.Size([2, 1, 2, 1, 2])#维度为0
torch.Size([2, 2, 1, 2])#维度为1
torch.Size([2, 1, 2, 1, 2])#维度为2
结论:将指定维度的size为1的数据去掉
9.非挤压
torch.unsqueeze(x,dim = 0\1\2\3)结果是不相同的
x = torch.zeros(2,1,2,1,2)
print(x.size())
y = torch.unsqueeze(x,1)
print(y.size())
结果:
torch.Size([2, 1, 2, 1, 2])
torch.Size([2, 1, 1, 2, 1, 2])在dim值添加1维
10.转置(两维)
torch.t(x)
例如:
x = torch.randn(2,3)
y = torch.t(x)
结果:
tensor([[0.6085, 0.5618, 0.6313],
[0.9452, 0.7196, 0.3068]])
tensor([[0.6085, 0.9452],
[0.5618, 0.7196],
[0.6313, 0.3068]])
11.取指定索引的值
torch.take(input,torch.LongTensor([0,1,2])
例如:
y = torch.rand(2,3)
print(y)
x = torch.take(y,torch.LongTensor([0,1]))#索引是数组的形式
print(x)
结果:
tensor([[0.3620, 0.8797, 0.6312],
[0.5947, 0.8049, 0.6122]])
tensor([0.3620, 0.8797])
12.交换指定维度的数据,对二维就像是转置
torch.tranlate(input,dim0,dim1)
例子:
y = torch.rand(2,3)
print(y)
x = torch.transpose(y, 0, 1)
print(x)
print(y)
结果:
tensor([[0.4197, 0.8285, 0.5399],
[0.0207, 0.1844, 0.4306]])
tensor([[0.4197, 0.0207],
[0.8285, 0.1844],
[0.5399, 0.4306]])
tensor([[0.4197, 0.8285, 0.5399],
[0.0207, 0.1844, 0.4306]])
多维:
x = torch.zeros(2,1,2,1,2)
print(x)
y = torch.transpose(x, 0, 1)
print(x)
print(y)
结果:
tensor([[[[[0., 0.]],
[[0., 0.]]]],
[[[[0., 0.]],
[[0., 0.]]]]])
tensor([[[[[0., 0.]],
[[0., 0.]]]],
[[[[0., 0.]],
[[0., 0.]]]]])
tensor([[[[[0., 0.]],
[[0., 0.]]],
[[[0., 0.]],
[[0., 0.]]]]])
结论:x不改变结构,y与x相比就是结构有所不同
13.移除张量的某维度:
torch.unbind(input,dim = 0)
14.stack连接
torch.stack(sequeue,dim = 0)
沿新的维度对输入的序列进行连接
序列中所有的张量都应为相同的Size。dim的范围在0到squeue的size之间
将Numpy数据到Tensor数据
import numpy as np
import torch
a = np.ones(5)
b = torch.from_numpy(a)
print(b)
#输出结果:tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
使用.cuda()使得Tensor变量在GPU上运行:
if torch.cuda.is_available():
x = x.cuda()
y = y.cuda()
x+y