深度學習100問
Author:louwill
Machine Learning Lab
所謂深監(jiān)督(Deep Supervision),就是在深度神經(jīng)網(wǎng)絡的某些中間隱藏層加了一個輔助的分類器作為一種網(wǎng)絡分支來對主干網(wǎng)絡進行監(jiān)督的技巧,用來解決深度神經(jīng)網(wǎng)絡訓練梯度消失和收斂速度過慢等問題。
深監(jiān)督作為一個訓練trick在2014年就已經(jīng)通過DSN(Deeply-Supervised Nets)提出來了。具體參見DSN論文。
DSN的一個缺點在于使用的網(wǎng)絡結構不夠深,且輔助的分類器為傳統(tǒng)的SVM模型。2015年的一篇Training Deeper Convolutional Networks with Deep Supervision的論文嘗試了在更深層結構的網(wǎng)絡中使用深監(jiān)督技巧。
深監(jiān)督的結構
通常而言,增加神經(jīng)網(wǎng)絡的深度可以一定程度上提高網(wǎng)絡的表征能力,但隨著深度加深,會逐漸出現(xiàn)神經(jīng)網(wǎng)絡難以訓練的情況,其中就包括像梯度消失和梯度爆炸等現(xiàn)象。為了更好的訓練深度網(wǎng)絡,我們可以嘗試給神經(jīng)網(wǎng)絡的某些層添加一些輔助的分支分類器來解決這個問題。這種輔助的分支分類器能夠起到一種判斷隱藏層特征圖質量好壞的作用。
既然明確了要通過深監(jiān)督來解決深度網(wǎng)絡難以訓練的問題,那么這個作為監(jiān)督分支結構應該加在神經(jīng)網(wǎng)絡的什么位置?論文作者根據(jù)一些經(jīng)驗法則和實驗給出了結論。作者先是把深監(jiān)督放在網(wǎng)絡最后一層,然后跑10-50次迭代,繪制出中間層的平均梯度值。最后作者將監(jiān)督分支添加在平均梯度消失(原文中平均梯度小于10_(-7))的那一層。隨迭代次數(shù)變化的各卷積層的平均梯度值如下圖所示。可以看到,Conv1-4層在迭代次數(shù)增加時平均梯度值都要小于10_(-7)。
帶有深監(jiān)督的一個8層深度卷積網(wǎng)絡結構如下圖所示。
帶有深監(jiān)督的一個13層深度卷積網(wǎng)絡結構如下圖所示。
其中各個模塊含義如下:
可以看到,圖中在第四個卷積塊之后添加了一個監(jiān)督分類器作為分支。Conv4輸出的特征圖除了隨著主網(wǎng)絡進入Conv5之外,也作為輸入進入了分支分類器。如圖所示,該分支分類器包括一個卷積塊、兩個帶有Dropout和ReLu的全連接塊和一個純全連接塊。
損失函數(shù)
以W和Ws分別表示主干網(wǎng)絡和深監(jiān)督分支的權重,則有:
輸出層softmax表示為:
主干網(wǎng)絡的損失函數(shù)為:
深監(jiān)督分支的softmax輸出表示為:
深監(jiān)督分支的損失函數(shù)為:
可以看到深監(jiān)督分支的損失函數(shù)取決于W,而不是Ws,因為分支結構中倒數(shù)第二層的S8特征圖關聯(lián)到主干網(wǎng)絡的卷積權重W1-4。
所以,聯(lián)合損失函數(shù)可以表示為:
其中α_t可以表示為隨訓練epoch t衰減的一個值:
看到這個聯(lián)合損失函數(shù)是不是有種正則化的味道,實際也正是如此,輔助loss能夠起到一種類似正則化的效果??梢钥吹?,Conv4在加深監(jiān)督和不加深監(jiān)督的平均梯度差異。如下圖所示:
Torch示例
下面以Torch為例實現(xiàn)一個帶深度監(jiān)督的卷積模塊。先定義卷積塊:
import torch.nn as nn
# 定義卷積塊
# 包含3x3卷積+BN+relu
def conv3x3_bn_relu(in_planes, out_planes, stride=1):
'3x3 convolution + BN + relu'
return nn.Sequential(
nn.Conv2d(in_planes, out_planes, kernel_size=3,
stride=stride, padding=1, bias=False),
BatchNorm2d(out_planes),
nn.ReLU(inplace=True),
)
帶有深監(jiān)督的卷積模塊如下:
class C1DeepSup(nn.Module):
def __init__(self, num_class=150, fc_dim=2048, use_softmax=False):
super(C1DeepSup, self).__init__()
self.use_softmax = use_softmax
self.cbr = conv3x3_bn_relu(fc_dim, fc_dim // 4, 1)
self.cbr_deepsup = conv3x3_bn_relu(fc_dim // 2, fc_dim // 4, 1)
# 最后一層卷積
self.conv_last = nn.Conv2d(fc_dim // 4, num_class, 1, 1, 0)
self.conv_last_deepsup = nn.Conv2d(fc_dim // 4, num_class, 1, 1, 0)
# 前向計算流程
def forward(self, conv_out, segSize=None):
conv5 = conv_out[-1]
x = self.cbr(conv5)
x = self.conv_last(x)
if self.use_softmax: # is True during inference
x = nn.functional.interpolate(
x, size=segSize, mode='bilinear', align_corners=False)
x = nn.functional.softmax(x, dim=1)
return x
# 深監(jiān)督模塊
conv4 = conv_out[-2]
_ = self.cbr_deepsup(conv4)
_ = self.conv_last_deepsup(_)
# 主干卷積網(wǎng)絡softmax輸出
x = nn.functional.log_softmax(x, dim=1)
# 深監(jiān)督分支網(wǎng)絡softmax輸出
_ = nn.functional.log_softmax(_, dim=1)
return (x, _)
在U-Net等經(jīng)典語義分割網(wǎng)絡中,使用深監(jiān)督技巧是一個通用做法。以上就是本文內容。
參考資料:
Deeply-Supervised Nets
Training Deeper Convolutional Networks with Deep Supervision