天天看點

resnet架構筆記

目的:深度殘差網絡(ResNets)具有較低的訓練誤差和測試誤差。

在論文中介紹了一個深層次的殘差學習架構來解決精準度下降問題。我們明确地讓這些層适合殘差映射,而不是寄希望于每一個堆疊層直接适合一個所需的底層映射。形式上,把H(x)作為所需的基本映射,讓堆疊的非線性層适合另一個映射F(x):=H(x)-x。那麼原映射便轉化成:F(x)+x。我們假設優化剩餘的映射,比優化原來未引用的映射更容易。如果身份映射是最佳的,那麼将剩餘的映射推為零,就比用一堆非線性層來适應身份映射更容易。

公式F(x)+x可以通過“快捷連接配接”前饋神經網絡實作。快捷連接配接是那些跳過中的一層或更多層。在我們的情景中,快捷連接配接簡單的執行身份映射,并将它們的輸出添加到疊加層的輸出。身份快捷連接配接添加既不産生額外的參數,也會增加不計算的複雜度。通過反向傳播的SGD,整個網絡仍然可以被訓練成終端到端的形式,并且可以在沒有修改器的情況下很容易的使用公共資料庫(例如Caffe)。

兩種resnet設計——bottle_neck

左圖bottle_neck=False,右圖bottle_neck=True;bottle_neck目的就是在resnet層數較多時,使用較少的參數數量。

{這兩種結構分别針對ResNet(左圖)和ResNet(右圖),一般稱整個結構為一個”building block“。其中右圖又稱為”bottleneck design”,目的一目了然,就是為了降低參數的數目,第一個1x1的卷積把256維channel降到64維,然後在最後通過1x1卷積恢複,整體上用的參數數目:1x1x256x64 + 3x3x64x64 + 1x1x64x256 = 69632,而不使用bottleneck的話就是兩個3x3x256的卷積,參數數目: 3x3x256x256x2 = 1179648,差了16.94倍。}

resnet架構筆記

一個stage中的兩個units

下圖為resnet18中一個stage的架構示意圖。左下unit負責降低特征圖檔的size,增加特征圖檔的channel;右上unit負責增加resnet深度,并不進行size上的變化。

resnet架構筆記

residual_unit mxnet 實作代碼

def residual_unit(data, num_filter, stride, dim_match, name, bottle_neck=True, bn_mom=0.9, workspace=256, memonger=False):
    """Return ResNet Unit symbol for building ResNet
    Parameters
    ----------
    data : str
        Input data
    num_filter : int
        Number of output channels
    bnf : int
        Bottle neck channels factor with regard to num_filter
    stride : tuple
        Stride used in convolution
    dim_match : Boolean
        True means channel number between input and output is the same, otherwise means differ
    name : str
        Base name of the operators
    workspace : int
        Workspace used in convolution operator
    """
    if bottle_neck:
        # the same as https://github.com/facebook/fb.resnet.torch#notes, a bit difference with origin paper
        bn1 = mx.sym.BatchNorm(data=data, fix_gamma=False, eps=2e-5, momentum=bn_mom, name=name + '_bn1')
        act1 = mx.sym.Activation(data=bn1, act_type='relu', name=name + '_relu1')
        conv1 = mx.sym.Convolution(data=act1, num_filter=int(num_filter*0.25), kernel=(1,1), stride=(1,1), pad=(0,0),
                                   no_bias=True, workspace=workspace, name=name + '_conv1')
        bn2 = mx.sym.BatchNorm(data=conv1, fix_gamma=False, eps=2e-5, momentum=bn_mom, name=name + '_bn2')
        act2 = mx.sym.Activation(data=bn2, act_type='relu', name=name + '_relu2')
        conv2 = mx.sym.Convolution(data=act2, num_filter=int(num_filter*0.25), kernel=(3,3), stride=stride, pad=(1,1),
                                   no_bias=True, workspace=workspace, name=name + '_conv2')
        bn3 = mx.sym.BatchNorm(data=conv2, fix_gamma=False, eps=2e-5, momentum=bn_mom, name=name + '_bn3')
        act3 = mx.sym.Activation(data=bn3, act_type='relu', name=name + '_relu3')
        conv3 = mx.sym.Convolution(data=act3, num_filter=num_filter, kernel=(1,1), stride=(1,1), pad=(0,0), no_bias=True,
                                   workspace=workspace, name=name + '_conv3')
        if dim_match:
            shortcut = data
        else:
            shortcut = mx.sym.Convolution(data=act1, num_filter=num_filter, kernel=(1,1), stride=stride, no_bias=True,
                                            workspace=workspace, name=name+'_sc')
        if memonger:
            shortcut._set_attr(mirror_stage='True')
        return conv3 + shortcut
    else:
        bn1 = mx.sym.BatchNorm(data=data, fix_gamma=False, momentum=bn_mom, eps=2e-5, name=name + '_bn1')
        act1 = mx.sym.Activation(data=bn1, act_type='relu', name=name + '_relu1')
        conv1 = mx.sym.Convolution(data=act1, num_filter=num_filter, kernel=(3,3), stride=stride, pad=(1,1),
                                      no_bias=True, workspace=workspace, name=name + '_conv1')
        bn2 = mx.sym.BatchNorm(data=conv1, fix_gamma=False, momentum=bn_mom, eps=2e-5, name=name + '_bn2')
        act2 = mx.sym.Activation(data=bn2, act_type='relu', name=name + '_relu2')
        conv2 = mx.sym.Convolution(data=act2, num_filter=num_filter, kernel=(3,3), stride=(1,1), pad=(1,1),
                                      no_bias=True, workspace=workspace, name=name + '_conv2')
        if dim_match:
            shortcut = data
        else:
            shortcut = mx.sym.Convolution(data=act1, num_filter=num_filter, kernel=(1,1), stride=stride, no_bias=True,
                                            workspace=workspace, name=name+'_sc')
        if memonger:
            shortcut._set_attr(mirror_stage='True')
        return conv2 + shortcut
           

參考博文

https://www.leiphone.com/news/201608/vhqwt5eWmUsLBcnv.html

http://www.mamicode.com/info-detail-2278503.html

繼續閱讀