上篇博客说了ResNet
和DenseNet
的原理,这次说说具体实现
def basic_block(input, in_features, out_features, stride, is_training, keep_prob):
"""Residual block"""
if stride == 1:
shortcut = input
else:
shortcut = tf.nn.avg_pool(input, [ 1, stride, stride, 1 ], [1, stride, stride, 1 ], 'VALID')
shortcut = tf.pad(shortcut, [[0, 0], [0, 0], [0, 0],
[(out_features-in_features)//2, (out_features-in_features)//2]])
current = conv2d(input, in_features, out_features, 3, stride)
current = tf.nn.dropout(current, keep_prob)
current = tf.contrib.layers.batch_norm(current, scale=True, is_training=is_training, updates_collections=None)
current = tf.nn.relu(current)
current = conv2d(current, out_features, out_features, 3, 1)
current = tf.nn.dropout(current, keep_prob)
current = tf.contrib.layers.batch_norm(current, scale=True, is_training=is_training, updates_collections=None)
return current + shortcut
def block_stack(input, in_features, out_features, stride, depth, is_training, keep_prob):
"""Stack Residual block"""
current = basic_block(input, in_features, out_features, stride, is_training, keep_prob)
for _d in xrange(depth - 1):
current = basic_block(current, out_features, out_features, 1, is_training, keep_prob)
return current
def conv2d(input, in_features, out_features, kernel_size, with_bias=False):
W = weight_variable([ kernel_size, kernel_size, in_features, out_features ])
conv = tf.nn.conv2d(input, W, [ 1, 1, 1, 1 ], padding='SAME')
if with_bias:
return conv + bias_variable([ out_features ])
return conv
def batch_activ_conv(current, in_features, out_features, kernel_size, is_training, keep_prob):
"""BatchNorm+Relu+conv+dropout"""
current = tf.contrib.layers.batch_norm(current, scale=True, is_training=is_training, updates_collections=None)
current = tf.nn.relu(current)
current = conv2d(current, in_features, out_features, kernel_size)
current = tf.nn.dropout(current, keep_prob)
return current
def block(input, layers, in_features, growth, is_training, keep_prob):
"""Dense Block"""
current = input
features = in_features
for idx in xrange(layers):
tmp = batch_activ_conv(current, features, growth, 3, is_training, keep_prob)
current = tf.concat(3, (current, tmp))
features += growth
return current, features
def model():
"""DenseNet on ImageNet"""
current = tf.reshape(xs, [ -1, 32, 32, 3 ]) # Input
current = conv2d(current, 3, 16, 3)
current, features = block(current, layers, 16, 12, is_training, keep_prob)
current = batch_activ_conv(current, features, features, 1, is_training, keep_prob)
current = avg_pool(current, 2)
current, features = block(current, layers, features, 12, is_training, keep_prob)
current = batch_activ_conv(current, features, features, 1, is_training, keep_prob)
current = avg_pool(current, 2)
current, features = block(current, layers, features, 12, is_training, keep_prob)
current = tf.contrib.layers.batch_norm(current, scale=True, is_training=is_training, updates_collections=None)
current = tf.nn.relu(current)
current = avg_pool(current, 8)
final_dim = features
current = tf.reshape(current, [ -1, final_dim ])
Wfc = weight_variable([ final_dim, label_count ])
bfc = bias_variable([ label_count ])
ys_ = tf.nn.softmax( tf.matmul(current, Wfc) + bfc )
代码不是完整的,只是表达最navie的思想核心部分