深度學習雜記(3)resnet殘差塊
阿新 • • 發佈:2019-01-24
深度學習的resnet的原理比較容易懂,但是具體的程式碼構建還是有些複雜,尤其是在tensorflow 的框架下構建比較複雜,在今天的博文中主要介紹了殘差單元的構建:
import collections import tensorflow as tf import tensorflow.contrib.slim as slim def subsample(inputs,factor,scope=None): if(factor==1): return inputs else: return slim.max_pool2d(inputs,[1,1],stride=factor,scope=scope)
上述這段程式碼的目的是為了構建一個降取樣的函式,目的是為了使輸入通道相同的preact的shape經過池化,shape達到一樣
def conv2d_same(inputs, num_outputs, kernel_size, stride, scope=None): if(stride==1): return slim.conv2d(inputs,num_outputs,kernel_size,stride=1,padding='SAME',scope=scope) else: net = slim.conv2d(inputs, num_outputs, 3, stride=1, padding='SAME') net = subsample(net, factor=stride) return net;
若stride==1,則對其做一個卷積取值,相當於全連線神經網路的作用,否則則是對其進行3*3卷積之後採取降取樣使得shortcut和residual的shape保持一致
def bottleneck(inputs, depth, depth_bottleneck, stride, outputs_collections=None, scope=None): """ Args: inputs: A tensor of size [batch, height, width, channels]. depth、depth_bottleneck:、stride三個引數是前面blocks類中的args rate: An integer, rate for atrous convolution. outputs_collections: 是收集end_points的collection """ with tf.variable_scope(scope, 'bottleneck_v2', ) as sc: depth_in = slim.utils.last_dimension(inputs.get_shape(), min_rank=4) # 最後一個維度,即輸出通道數 preact = slim.batch_norm(inputs, activation_fn=tf.nn.relu, scope='preact') if depth == depth_in: # 如果殘差單元的輸入通道數和輸出通道數一致,那麼按步長對inputs進行降取樣 shortcut = subsample(inputs, stride, 'shortcut') else: # 如果不一樣就按步長和1*1的卷積改變其通道數,使得輸入、輸出通道數一致 shortcut = slim.conv2d(preact, depth, [1, 1], stride=stride, normalizer_fn=None, activation_fn=None, scope='shortcut') # 先是一個1*1尺寸,步長1,輸出通道數為depth_bottleneck的卷積 residual = slim.conv2d(preact, depth_bottleneck, [1, 1], stride=1, scope='conv1') # 然後是3*3尺寸,步長為stride,輸出通道數為depth_bottleneck的卷積 residual = conv2d_same(residual, depth_bottleneck, 3, stride, scope='conv2') # 最後是1*1卷積,步長1,輸出通道數depth的卷積,得到最終的residual。最後一層沒有正則項也沒有啟用函式 residual = slim.conv2d(residual, depth, [1, 1], stride=1, normalizer_fn=None, activation_fn=None, scope='conv3') # 將降取樣的結果和residual相加 output = shortcut + residual return slim.utils.collect_named_outputs(outputs_collections, sc.name, output)
最後是整個殘差塊的設計。