Pytorch系列之——Pytorch的Tensor(张量)
张量的构建
- Tensor概念
- Tensor创建一:直接创建
- Tensor创建二:依据数值创建
- Tensor创建三:依据概率创建
张量是什么?
张量其实就是一个多维数组,它是标量、向量、矩阵的高维拓展:
Tensor与Variable
Variable是torch.autograd中的数据类型,主要用于封装Tensor,进行自动求导,接下来先来看下torch.autograd.Variable这个数据类型,理解了Variable其实对于理解张量是有帮助的:
可以看到,Variable中包含了5个属性:
- data:表示被包装的Tensor
- grad:表示data的梯度
- grad_fn:表示创建Tensor的Function,是自动求导的关键
- requires_grad:指示是否需要梯度,并不是所有的张量都需要计算梯度,若张量需要计算梯度,那么设置requires_grad=True,反之设置requires_grad=False
- is_leaf:指示是否是叶子结点(张量)
Tensor
从Pytorch0.4.0版本开始,Variable就并入了Tensor,那么我们来看下torch.Tensor这个数据类型的具体细节:
torch.Tensor主要包含8个数据类型,其中有5个属性上面介绍Variable时已经讲述过了,所以主要介绍一下其余的3个属性:
- dtype:张量的数据类型,如torch.FloatTensor,torch.cuda.FloatTensor
- shape:张量的形状,如(64,3,224,224)
- device:张量所在的设备,GPU/CPU,是加速的关键
张量的创建
一、直接创建
torch.tensor()
功能:从data创建tensor
- data:数据,可以是list,numpy
- dtype:数据类型,默认与data的一致
- device:所在设备,cuda/cpu
- requires_grad:是否需要梯度
- pin_memory:是否存于锁页内存
torch.from_numpy(ndarray)
功能:从numpy创建tensor
需要注意的是,从torch.from_numpy创建的tensor与原ndarray共享内存,当修改其中一个的数据,另外一个也将会被改动。
二、依据数值创建
torch.zeros()
功能:依size创建全0张量
- size:张量的形状,如(3,3),(3,224,224)
- out:输出的张量
- layout:内存中布局形式,有stride,sparse_coo等
- device:所在设备,gpu/cpu
- requires_grad:是否需要梯度
torch.zeros_like()
功能:依input形状创建全0张量
- input:创建与input同形状的全0张量
- dtype:数据类型
- layout:内存中布局形式
除此之外,还有torch.ones()、torch.ones_like()
功能:依input形状创建全1张量
- size:张量的形状,如(3,3)、(3,224,224)
- dtype:数据类型
- layout:内存中布局形式
- device:所在设备,gpu/cpu
- requires_grad:是否需要梯度
torch.full()、torch.full_like()
功能:依inputing形状创建全值为fill_value的张量
- size:张量的形状,如(3,3)
- fill_value:张量的值
torch.arange()
功能:创建等差的1维张量
- start:数列起始值
- end:数列结束值
- step:数列公差,默认为1
torch.linspace()
功能:创建均分的1维张量
- start:数列起始值
- end:数列结束值
- steps:数列长度(注意和数列步长进行区别)
torch.logspace()
功能:创建对数均分的1维张量
- start:数列起始值
- end:数列结束值
- steps:数列长度
- base:对数函数的底,默认为10
torch.eye()
功能:创建单位对角矩阵(2维张量)
- n:矩阵行数
- m:矩阵列数
三、依概率分布创建张量
torch.normal()
功能:生成正态分布(高斯分布)
- mean:均值
- std:标准差
有四种模式:
1.mean为标量,std为标量
2.mean为标量,std为张量
3.mean为张量,std为标量
4.mean为张量,std为张量
更常用的是:torch.randn()、torch.randn_like()
功能:生成标准正态分布
- size:张量的形状
torch.randint()
功能:在区间[0,1)上,生成均匀分布
torch.randint_like()
功能:在区间[low,high)生成整数均匀分布
-
size:张量的形状
最后两个方法:
torch.randperm()
功能:生成从0—n-1的随机排列 -
n:张量的长度
torch.bernoulli()
功能:以input为概率,生成伯努利分布(0-1分布,两点分布) -
input:概率值
张量操作与线性回归
- 张量的操作:拼接、切分、索引和变换
- 张量的数学运算
- 线性回归
一、张量拼接与切分
1.1 torch.cat()
功能:将张量按维度dim进行拼接
- tensors:张量序列
- dim:要拼接的维度
1.2 torch.stack()
功能:在新创建的维度dim上进行拼接
- tensors:张量序列
- dim:要拼接的维度
需要注意的是torch.cat()和torch.stack()的区别在于,前者不会扩张张量的维度,而后者会扩张张量的维度。
从代码中我们可以看出,torch.stack()方法对dim=0维度进行了扩张。
1.3 torch.chunk()
功能:将张量按维度dim进行平均切分
返回值:张量列表
注意事项:若不能整除,最后一份张量小于其他张量
- input:要切分的张量
- chunks:要切分的份数
- dim:要切分的维度
1.4 torch.split()
功能:将张量按维度dim进行切分
返回值:张量列表
- tensor:要切分的张量
- split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分
- dim:要切分的维度
二、张量索引
2.1 torch.index_select()
功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量
- input:要索引的张量
- dim:要索引的维度
- index:要索引数据的序号
2.2 torch.masked_select()
功能:按mask中的True进行索引
返回值:一维张量
- input:要索引的张量
- mask:与input同形状的布尔类型张量
三、张量变换
3.1 torch.reshape()
功能:变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存
- input:要变换的张量
- shape:新张量的形状
3.2 torch.transpose()
功能:交换张量的两个维度
- input:要交换的张量
- dim0:要交换的维度
- dim1:要交换的维度
3.3 torch.t()
功能:2维张量转置,对矩阵而言,等价于:
torch.transpose(input,0,1)
3.4 torch.squeeze()
功能:压缩长度为1的维度(轴)
- dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除;
3.5 torch.unsqueeze()
功能:依据dim扩展维度
- dim:扩展的维度
张量数学运算
加减乘除;对数、指数、幂函数;三角函数,用的时候自行查阅即可:
在这里着重介绍一下torch.add()
torch.add():
功能:逐元素计算input+alpha*other
- input:第一个张量
- alpha:乘项因子
- other:第二个张量
以上两个方法在优化过程中经常会使用到。
线性回归
线性回归是分析一个变量与另外一(多)个变量之间关系的方法
线性回归求解步骤:
-
确定模型
Model: y=wx+b -
选择损失函数
通常选择均方误差作为线性回归的损失函数。 -
求解梯度并更新w,b
w= w - LR * w.grad
b= b - LR * w.grad
计算图与动态图机制
- 计算图
- Pytorch的动态图机制
深度学习其实就是对张量进行一系列操作,随着操作种类和数量的增多,会导致各种各样想不到的问题。比如,多个操作之间应该并行还是顺序执行?如何协同不同底层设备?以及如何避免各种冗余的操作?…计算图就是为了解决这些问题而产生的。
计算图
计算图是用来描述运算的有向无环图,计算图有两个主要元素:结点(node)和边(edge)。其中,结点表示数据,如向量、矩阵、张量;边表示运算,如加减乘除卷积等。
用计算图表示:y=(x+w) * (w+1)
使用计算图不仅使运算更加简洁,更重要的作用是它使得梯度求导更加方便。
非叶子结点的梯度是会被释放掉的(retain_grad()方法可以保存梯度)
grad_fn:记录创建该张量时所用的方法:
- y_grad_fn=(MulBackward0)
- a.grad_fn=(AddBackward0)
- b.grad_fn=(AddBackward0)
a和b是通过加法运算得到的,y是通过乘法运算得到的
动态图
pytorch采用的是动态图机制,而tensorflow采用的是静态图机制,那么二者的差异体现在哪儿呢?
动态图是运算与搭建同时进行,而静态图是先搭建图,之后再运算,根据计算图的搭建方式,可将计算图分为动态图(灵活、易调节)和静态图(高效、不灵活)。
静态图——Tensorflow:
先创建计算图,之后才可以在Input处进行数据的输入。
动态图——Pytorch:
计算图的构建是和数据的输入同时进行的。
autograd与逻辑回归
- torch.autograd
- 逻辑回归
torch.autograd.backward()
功能:自动求取梯度
- tensors:用于求导的张量,如loss
- retain_graph:保存计算图
- create_graph:创建导数计算图,用于高阶求导
- grad_tensors:多梯度权重(当有多个Loss需要计算梯度时,需要计算各个梯度权重之间的比例)
torch.autograd.grad()
功能:求取梯度
- outputs:用于求导的张量,如loss
- inputs:需要梯度的张量
- create_graph:创建导数计算图,用于高阶求导
- retain_graph:保存计算图
- grad_outputs:多梯度权重
autograd小贴士:
- 梯度不自动清零(使用grad.zero_()方法)
- 依赖于叶子结点的结点,requires_grad默认为True
- 叶子结点不可执行in-place,in-place操作就是在原始内存中去改变这个数据
逻辑回归
逻辑回归(对数几率回归)是线性的二分类模型:
线性回归是分析自变量x与因变量y(标量)之间关系的方法;
逻辑回归是分析自变量x与因变量y(概率)之间关系的方法。
机器学习模型训练的五个步骤,接下来的关于pytorch构建的模型都是基于这五大步骤来进行:
总结
这次主要学习了pytorch框架中张量的基本操作和运算,包括对张量的介绍和构建,其中创建张量可以通过三种方式来创建,分别为:直接构建、根据数值构建和根据概率构建。此外,比较重要的还有torch.Tensor数据类型中包含的8个属性,这些应该在理解的基础上记忆。其中比较细节的部分主要是对张量的一些操作和数学运算,并用最简单的线性回归作为案例。篇末介绍了pytorch中最为重要的计算图和动态图机制,这里需要和Tensorflow的静态图机制进行区分。最后引出了机器学习模型训练的五个步骤,即:数据模块、模型模块、损失函数、优化器和迭代训练,这五个步骤贯穿机器学习模型训练的始终。