深度学习是一种基于神经网络的机器学习。
神经网络模型计算中会涉及大量的向量、矩阵和张量计算。
向量计算:
矩阵计算:
张量(tensor),向量可看做一维张量。矩阵可看做二维张量。
例如:
黑白图片是二维矩阵(图片的高h,宽w)
彩色图片是三维张量(图片高度h,宽度w,图片的通道数目c)( h × w × c h\times w \times c h×w×c)(彩色图片有rgb三个通道 c=3)
在进行深度学习的过程中,常用到四维张量,增加的一个维数为迷你批次(mni-batch)的大小,可以认为是每次输入深度神经网络图片的数目。
根据张量的四个维度排列方式可以分为NCHW和NHWC两种:
不同的深度框架可能会采用不同的排列方式,需要根据具体使用的框架来决定具体的维数排列应该是什么
深度学习网络构造中,使用各种线性变换,主要分为两类:
以图片为例
对于每个像素点,有1个、3个或4个通道,分别对应于灰度、RGB、RGBA图像。
每个通道的取值范围为0~255之间的整数。
由于图片大小(高度、宽度)各不相同,而网络训练过程中会批量处理图片,所以常通过最近邻差值、双线性差值等方法把图片调整为统一的目标大小
调整好同一大小后,再将所有像素的所有通道除以255,转换为0~1的浮点数
为增加图片多样性,常在调整图片大小前会对图片进行一些特殊处理,如:
上述操作的目的是扩增数据集,增加神经网络的泛化能力
转换为张量后,还需要归一化才能输入神经网络。
归一化让数据分布规整,有效增加神经网络训练的数值稳定性,有利于优化损失函数,从而提高训练结果的准确率。
下一层神经网络的每个值都和前一层神经网络的每个值相关联,这种神经网络连接方式为全连接层(Fully Connected Layer,FC Layer),对应的线性变换为全连接线性变换。
对于全连接层,可以用矩阵来描述连接方式,即如果对一个n大小的输入向量,将其变化为m大小的向量,需要一个 m × n m \times n m×n大小的矩阵来描述这种线性变换,我们称这种线性变换的矩阵为连接的权重(weight)。
对于神经网络来说,权重是一个经过一定随机初始化(比如权重的每个分量值都初始化为标准的正态分布),权重在神经网络的训练过程中会逐渐向着让模型更好地符合数据分布的方向变化,这个过程称为模型的优化(optimization)。
除权重外,我们一般还会给线性变换之后的输出统一加一个可训练的参数,这个参数是标量,即为一个实数,我们称这个参数为偏置(bias)
全连接的线性变换由于前一层和后一层所有的神经元之间都有一对一的连接关系,也称为稠密连接层 (Dense Layer)。
在实际的应用过程中,这种神经元之间关系的描述可能有许多冗余,对于神经网络模型的训练并不是很友好。
为此,人们发明了一系列稀疏(Sparse)的连接方式来描述前后两层神经元之间的连接关系,其中最有名的一个就是卷积层(Convolution Layer, Conv Layer),对应的神经网络称为卷积神经网络(Convolution Neural Networks, CNN)。
如图所示,左边是输入的一张图片(某一通道), 右边是一个3x3的卷积核(Convolution Kernel,或称为Fiter)。
卷积核的每个分量都是可训练的实数,也称为权重。
在运算过程中,
需要从输入图片中取出和卷积核大小相同的块区域(左边虚线方框的区域),
然后把区域里面的数和卷积核的权重按照一一对应的方式相乘,
并把所有的乘积求和,作为最后的输出。
通过变化虚线框的位置(按照箭头方向移动,得到对应行列的值,其中移动的步长Stride是一个可以调节的参数),可以得到新的输出,这个过程即为卷积的过程。
由于卷积核的权重只和输入的局部区域相连接,因此,这里称卷积的连接方式为稀疏连接。
在实际的运算中,卷积运算一般是转换为矩阵运算来进行的。
首先是把图片按照卷积的顺序转换为矩阵,对应的函数称之为Im2Col (Image to Columns)。
其中,列的大小和卷积核的大小一致, 比如3x3的卷积核对应的矩阵的列就是9,行的方向则和卷积的方向一致。
然后把卷积核也转换为矩阵,
其中行的大小和卷积核大小一致,列的大小和不同的卷积核的数目一致
(上图所示的是一个卷积核的卷积过程,实践中可以有多个卷积核,对应不同通道的输出)。
然后对着两个矩阵做乘法计算,对应调用的函数称之为GEMM (GEneral Matrix Muliplication)。
相对于全连接的矩阵乘法而言,卷积的矩阵乘法由于卷积核的大小一般比较小(1x1、3x3、5x5等)。
相对而言,权重数目也比较小,能有效地减少可训练参数的数目,加快模型的训练和收敛速度。
因此,卷积神经网络在深度学习模型中得到了广泛的应用。
激活函数是非线性函数,通过对线性变换中输出结果的每个分量都应用激活函数,可以输出非线性的结果。
实践中,人们主要应用Sigmoid函数、Tanh函数和ReLU函数。
根据神经网络预测的目标不同,在最终隐藏层和输出层之间,会使用不同的激活函数。
静态图是在计算之前预先构建一个计算图,图中的节点是运算操作,图中的边则是运算张量。
在使用框架时,一般使用配置文件或者不同语言的接口函数预先构建出深度学习模型对应的静态图,然后在静态图中输入张量,框架的执行引擎会根据输入的张量进行计算,最后输出深度学习模型的计算结果。
静态图不必在每次计算前都重新够计算,有效减少了计算图构建的时间消耗。
但是静态图为了效率牺牲了灵活性,因此在静态计算图中使用条件控制(如循环和判断)会不太方便。
其次静态图在构建时只能检查一些静态参数(如输入、输出张量形状是否合理),一些问题无法在图构建阶段被排查,只能在引擎执行时被发现。
因此,代码调试方面,静态计算图比较低效,基于静态图的深度学习框架上手比较困难。
静态图框架:TensorFlow、Caffe
动态图框架:Pytorch