对于许多应用来说,使用由一个简单的层序列组成的网络就已足够。
但是,某些应用要求网络具有更复杂的层次图结构,其中的层可接收来自多个层的输入,也可以输出到多个层。这些类型的网络通常称为有向无环图 (DAG) 网络。
残差网络就是一种 DAG 网络,其中的残差(或快捷)连接会绕过主网络层。残差连接让参数梯度可以更轻松地从输出层传播到较浅的网络层,从而能够训练更深的网络。增加网络深度可在执行更困难的任务时获得更高的准确度。
定义网络架构
残差网络架构由以下组件构成:
主分支 - 顺序连接的卷积层、批量归一化层和 ReLU 层。
残差连接 - 绕过主分支的卷积单元。残差连接和卷积单元的输出按元素相加。当激活区域的大小变化时,残差连接也必须包含 1×1 卷积层。残差连接让参数梯度可以更轻松地从输出层流到较浅的网络层,从而能够训练更深的网络。
创建主分支
首先创建网络的主分支。主分支包含五部分。
初始部分 - 包含图像输入层和带激活函数的初始卷积层。
三个卷积层阶段 - 分别具有不同的特征大小(32×32、16×16 和 8×8)。每个阶段包含 N 个卷积单元。在示例的这一部分中,N = 2。每个卷积单元包含两个带激活函数的 3×3 卷积层。netWidth 参数是网络宽度,定义为网络第一卷积层阶段中的过滤器数目。第二阶段和第三阶段中的前几个卷积单元会将空间维度下采样二分之一。为了使整个网络中每个卷积层所需的计算量大致相同,每次执行空间下采样时,都将过滤器的数量增加一倍。
最后部分 - 包含全局平均池化层、全连接层、softmax 层和分类层。
使用 convolutionalUnit(numF,stride,tag) 创建一个卷积单元。numF 是每一层中卷积过滤器的数量,stride 是该单元第一个卷积层的步幅,tag 是添加在层名称前面的字符数组。convolutionalUnit 函数在示例末尾定义。
为所有层指定唯一名称。卷积单元中的层的名称以 'SjUk' 开头,其中 j 是阶段索引,k 是该阶段内卷积单元的索引。例如,'S2U1' 表示第 2 阶段第 1 单元。
**
netWidth = 16; layers = [ imageInputLayer([32 32 3],'Name','input') convolution2dLayer(3,netWidth,'Padding','same','Name','convInp') batchNormalizationLayer('Name','BNInp') reluLayer('Name','reluInp') convolutionalUnit(netWidth,1,'S1U1') additionLayer(2,'Name','add11') reluLayer('Name','relu11') convolutionalUnit(netWidth,1,'S1U2') additionLayer(2,'Name','add12') reluLayer('Name','relu12') convolutionalUnit(2*netWidth,2,'S2U1') additionLayer(2,'Name','add21') reluLayer('Name','relu21') convolutionalUnit(2*netWidth,1,'S2U2') additionLayer(2,'Name','add22') reluLayer('Name','relu22') convolutionalUnit(4*netWidth,2,'S3U1') additionLayer(2,'Name','add31') reluLayer('Name','relu31') convolutionalUnit(4*netWidth,1,'S3U2') additionLayer(2,'Name','add32') reluLayer('Name','relu32') averagePooling2dLayer(8,'Name','globalPool') fullyConnectedLayer(10,'Name','fcFinal') softmaxLayer('Name','softmax') classificationLayer('Name','classoutput') ];