參考自:https://blog.csdn.net/sinat_42239797/article/details/90646935
1.卷積神經網絡的結構
卷積神經網絡(CNN)由輸入層、卷積層、激活函數、池化層、全連接層組成,
即INPUT(輸入層)-CONV(卷積層)-RELU(激活函數)-POOL(池化層)-FC(全連接層)
2.卷積神經網絡的計算
計算公式為:
其中:
- N:輸出大小
- W:輸入大小
- F:卷積核大小
- P:填充值大小
- S:步長大小
比如:
nn.Conv2d(in_channels=3,out_channels=96,kernel_size=11,stride=4,padding=2)
卷積一層的幾個參數:
- in_channels=3:表示輸入的通道數。由於是RGB類型,所以通道數為3
- out_channels=96:表示輸出的通道數,設定輸出通道數的96(可以根據自己的需要來設置)
- kernel_size=12:表示卷積核的大小是12x12的,也就是上面的F=12
- stride=4:表示步長為4,也就是S=4
- padding=2:表示填充值的大小為2,也就是P=2
3.以AlexNet為例進行詳解
AlexNet網絡結構圖如下圖所示:
可以看出該網絡有8層:5個卷積層,3個全連接層。
卷積神經網絡的設置包括卷積層的設置以及正反向傳播的設置
卷積層的設置代碼如下:
self.conv1 = torch.nn.Sequential( #input_size = 227*227*3
torch.nn.Conv2d(in_channels=3,out_channels=96,kernel_size=11,stride=4,padding=0),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=3, stride=2) #output_size = 27*27*96
)
self.conv2 = torch.nn.Sequential( #input_size = 27*27*96
torch.nn.Conv2d(96, 256, 5, 1, 2),
torch.nn.ReLU(),
torch.nn.MaxPool2d(3, 2) #output_size = 13*13*256
)
self.conv3 = torch.nn.Sequential( #input_size = 13*13*256
torch.nn.Conv2d(256, 384, 3, 1, 1),
torch.nn.ReLU(), #output_size = 13*13*384
)
self.conv4 = torch.nn.Sequential( #input_size = 13*13*384
torch.nn.Conv2d(384, 384, 3, 1, 1),
torch.nn.ReLU(), #output_size = 13*13*384
)
self.conv5 = torch.nn.Sequential( #input_size = 13*13*384
torch.nn.Conv2d(384, 256, 3, 1, 1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(3, 2) #output_size = 6*6*256
)
self.dense = torch.nn.Sequential(
torch.nn.Linear(9216, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 50)
)
卷積一層
self.conv1 = torch.nn.Sequential( #input_size = 227*227*3
torch.nn.Conv2d(in_channels=3,out_channels=96,kernel_size=11,stride=4,padding=0),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=3, stride=2) #output_size = 27*27*96
)
可以看到輸入為227x227x3,也就是說size為227x227,通道數為3,為RGB圖像。
torch.nn.Conv2d(in_channels=3,out_channels=96,kernel_size=11,stride=4,padding=0)
可以計算得到輸出結果為:\(N = (227-11+2\times0)/4+1=55\),即卷積后的尺寸是55x55x96的。
注:其中的96是48x2=96看圖第一層是有上下兩個部分,每個部分是寬是48,所有一共是96個卷積核。
torch.nn.ReLU()
使用激活函數ReLU,在神經元中的作用的:通過加權的輸入進行非線性組合產生非線性決策邊界。簡單的來說就是增加非線性作用。
在深層卷積神經網絡中使用激活函數同樣也是增加非線性,主要是為了解決sigmoid函數帶來的梯度消失問題。
torch.nn.MaxPool2d(kernel_size=3, stride=2) #output_size = 27*27*96
MaxPool 最大池化層,池化層在卷積神經網絡中的作用在於特征融合和降維。池化也是一種類似的卷積操作,只是池化層的所有參數都是超參數,是學習不到的。
這里的最大池化操作:將2x2尺寸內的所有像素值取最大值作為輸出通道的像素值。
輸出大小的計算和卷積層的計算過程一樣:\(N=(W-F+2P)/S+1=(55-3+2\times0)/2+1=27\)
則輸出為27x27x96
卷積二層
self.conv2 = torch.nn.Sequential( #input_size = 27*27*96
torch.nn.Conv2d(96, 256, 5, 1, 2),
torch.nn.ReLU(),
torch.nn.MaxPool2d(3, 2) #output_size = 13*13*256
)
可以看到卷積2層的輸入為96x27x27的,也就是上一層的輸出,從這里也就知道,上一層的輸出為下一層的輸入。
卷積2層的計算過程和卷積1層的計算過程是一樣的,具體不詳細描述
卷積2層最終輸出為13x13x256,本層的神經元數目為27x27x256 =186642個
卷積3層最終輸出為13x13x384,本層的神精元數目為13x13x384 =64896個
卷積4層最終輸出為13x13x384,本層的神精元數目為13x13x384 = 64896個
卷積5層最終輸出為6x6x256,本層的神精元數目為6x6x256=9216個
全連接層
全連接層的作用主要是負責邏輯推斷,所有的參數都必須學習得到。
self.dense = torch.nn.Sequential(
torch.nn.Linear(9216, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 4096),
torch.nn.ReLU(),
torch.nn.Dropout(0.5),
torch.nn.Linear(4096, 50)
)
由結構圖可以看到有3層全連接層
第一層全連接層(第六層)
作用:
- 鏈接卷積層的輸出
- 去除空間信息(通道數),將三維矩陣轉變為向量。
其操作可以看成是輸入圖像為\(W\times H\times C\),卷積核的尺寸為\(W\times H\times C\),這樣卷積后的尺寸為\(1\times 1\times 1\),這樣整個圖像變成了一個數,一共有K個數(第一層全連接層后的神經元數)。
第六層輸入數據的尺寸是6x6x256,采用6x6x256尺寸的濾波器對第六層的輸入數據進行卷積運算;每個6x6x256尺寸的濾波器對第六層的輸入數據進行卷積運算生成一個運算結果,通過一個神經元輸出這個運算結果;共有4096個6x6x256尺寸的濾波器對輸入數據進行卷積,通過4096個神經元的輸出運算結果;然后通過ReLU激活函數以及dropout運算輸出4096個本層的輸出結果值。
第二層全連接層(第七層)
第6層輸出的4096個數據與第7層的4096個神經元進行全連接,然后經由ReLU和Dropout進行處理后生成4096個數據。
第三層全連接層(第八層)
第7層輸入的4096個數據與第8層的50個神經元進行全連接,經過訓練后輸出被訓練的數值。
正向傳播的順序設置
def forward(self, x): #正向傳播過程
conv1_out = self.conv1(x)
conv2_out = self.conv2(conv1_out)
conv3_out = self.conv3(conv2_out)
conv4_out = self.conv4(conv3_out)
conv5_out = self.conv5(conv4_out)
'''
x.view(x.size(0), -1)的用法:
在CNN中,因為卷積或者池化之后需要連接全連接層,所以需要把多維度的tensor展平成一維,因此用它來實現(其實就是將多維數據展平為一維數據方便后面的全連接層處理)
'''
res = conv5_out.view(conv5_out.size(0), -1)
out = self.dense(res)
return out
常見的卷積層設置問題
-
為什么是cove2d?
cove1d:用於文本數據,只對寬度進行卷積,對高度不進行卷積
cove2d:用於圖像數據,對寬度和高度都進行卷積 -
為什么卷積核大小5x5寫一個5?
Conv2d(輸入通道數, 輸出通道數, kernel_size(長和寬)),當卷積核為方形時,只寫一個就可以
卷積核不是方形時,長和寬都要寫:self.conv1 = nn.Conv2d(3, 6, (5,3))
-
池化層的作用
maxpooling有局部不變性而且可以提取顯著特征的同時降低模型的參數,從而降低模型的過擬合。
因為只是提取了顯著特征,而舍棄了不顯著的信息,使得模型的參數減少了,從而一定程度上可以緩解過擬合的產生。