對于許多應(yīng)用來說,使用由一個簡單的層序列組成的網(wǎng)絡(luò)就已足夠。但是,某些應(yīng)用要求網(wǎng)絡(luò)具有更復(fù)雜的層次圖結(jié)構(gòu),其中的層可接收來自多個層的輸入,也可以輸出到多個層。這些類型的網(wǎng)絡(luò)通常稱為有向無環(huán)圖 (DAG) 網(wǎng)絡(luò)。殘差網(wǎng)絡(luò)就是一種 DAG 網(wǎng)絡(luò),其中的殘差(或快捷)連接會繞過主網(wǎng)絡(luò)層。殘差連接讓參數(shù)梯度可以更輕松地從輸出層傳播到較淺的網(wǎng)絡(luò)層,從而能夠訓(xùn)練更深的網(wǎng)絡(luò)。增加網(wǎng)絡(luò)深度可在執(zhí)行更困難的任務(wù)時獲得更高的準(zhǔn)確度。
定義網(wǎng)絡(luò)架構(gòu)
殘差網(wǎng)絡(luò)架構(gòu)由以下組件構(gòu)成:
主分支 - 順序連接的卷積層、批量歸一化層和 ReLU 層。
殘差連接 - 繞過主分支的卷積單元。殘差連接和卷積單元的輸出按元素相加。當(dāng)激活區(qū)域的大小變化時,殘差連接也必須包含 1×1 卷積層。殘差連接讓參數(shù)梯度可以更輕松地從輸出層流到較淺的網(wǎng)絡(luò)層,從而能夠訓(xùn)練更深的網(wǎng)絡(luò)。
創(chuàng)建主分支
首先創(chuàng)建網(wǎng)絡(luò)的主分支。主分支包含五部分。
初始部分 - 包含圖像輸入層和帶激活函數(shù)的初始卷積層。
三個卷積層階段 - 分別具有不同的特征大?。?2×32、16×16 和 8×8)。每個階段包含 N 個卷積單元。在示例的這一部分中,N = 2。每個卷積單元包含兩個帶激活函數(shù)的 3×3 卷積層。netWidth 參數(shù)是網(wǎng)絡(luò)寬度,定義為網(wǎng)絡(luò)第一卷積層階段中的過濾器數(shù)目。第二階段和第三階段中的前幾個卷積單元會將空間維度下采樣二分之一。為了使整個網(wǎng)絡(luò)中每個卷積層所需的計算量大致相同,每次執(zhí)行空間下采樣時,都將過濾器的數(shù)量增加一倍。
最后部分 - 包含全局平均池化層、全連接層、softmax 層和分類層。
使用 convolutionalUnit(numF,stride,tag) 創(chuàng)建一個卷積單元。numF 是每一層中卷積過濾器的數(shù)量,stride 是該單元第一個卷積層的步幅,tag 是添加在層名稱前面的字符數(shù)組。convolutionalUnit 函數(shù)在示例末尾定義。
為所有層指定唯一名稱。卷積單元中的層的名稱以 'SjUk' 開頭,其中 j 是階段索引,k 是該階段內(nèi)卷積單元的索引。例如,'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')
];