sallyyoungsh 2018-07-02
在这篇文章中,我们将学习如何从头开始创建多尺度神经网络。这不同于典型的前馈神经网络,其中每层的输出仅连接到后续层。在多尺度神经网络中,较低层的输出也被馈送到分类器中。这允许模型利用较低层识别的较低级特征。
在严格的前馈神经网络中,输出仅馈送到上面的层。最后的分类器只接收来自前一层的输入。使用TensorFlow构建这样的网络非常简单。以下是可用于使用TensorFlow创建严格前馈神经网络(具有两个卷积和一个完全连接层)的Python代码。
创建架构
一些辅助方法来定义我们将要使用的权重、偏差和层
def get_weights_biases(mu, sigma):
weights = {
'wc1' : tf.Variable(tf.truncated_normal([5, 5, 1, 6], mu, sigma)),
'wc2' : tf.Variable(tf.truncated_normal([5, 5, 6, 16], mu, sigma)),
'wd1' : tf.Variable(tf.truncated_normal([400, 120], mu, sigma)),
'out' : tf.Variable(tf.truncated_normal([120, n_classes], mu, sigma))
}
biases = {
'bc1' : tf.Variable(tf.zeros([6])),
'bc2' : tf.Variable(tf.zeros([16])),
'bd1' : tf.Variable(tf.zeros([120])),
'out' : tf.Variable(tf.zeros([n_classes]))
}
return weights, biases
def conv2d(x, W, b, s=1):
conv = tf.nn.conv2d(x, W, strides=[1, s, s, 1], padding='VALID')
conv = tf.nn.bias_add(conv, b)
return tf.nn.relu(conv)
def conv2d(x, W, b, s=1):
conv = tf.nn.conv2d(x, W, strides=[1, s, s, 1], padding='VALID')
conv = tf.nn.bias_add(conv, b)
return tf.nn.relu(conv)
def maxpooling2D(x, k=2):
return tf.nn.max_pool(x,
ksize=[1, k, k, 1],
strides=[1, k, k, 1],
padding="SAME")
现在定义主架构
def LeNet(x, keep_prob):
mu = 0
sigma = 0.1
W, b = get_weights_biases(mu, sigma)
#first layer
#Input = 32 x 32 x 1
#Output = 14 x 14 x 6
conv1 = conv2d(x, W['wc1'], b['bc1'])
conv1 = maxpooling2d(conv1)
print("1st layer shape : ", conv1.get_shape().as_list())
#second layer
#Input = 14 x 14 x 6
#Output = 5 x 5 x 16
conv2 = conv2d(conv1, W['wc2'], b['bc2'])
conv2 = maxpooling2d(conv2)
print("2nd layer shape : ", conv2.get_shape().as_list())
#flatten the conv layer output
flatten = Flatten(conv2)
#third layer
#Input = 400
#Output = 120
fd1 = tf.add(tf.matmul(concatenated_layer, W['wd1']), b['bd1'])
fd1 = tf.nn.relu(fd1)
fd1 = tf.nn.dropout(fd1, keep_prob)
print("Third layer shape : ", fd1.get_shape().as_list())
#output layer
#Input = 120
#Output = n_classes
out = tf.add(tf.matmul(fd1, W['out']), b['out'])
return out
在多尺度架构中,初始卷积层的输出在被二次采样后直接馈入分类器。这具有的优点是由较低层获得的信息对最终输出具有更多的影响。
创建体系结构
作为初始步骤,我们将不得不改变flattened 层权重的尺寸,因为它现在输入的将是第二卷积层的输出和第一卷积层的二次采样输出。如果您按照每个图层上方提到的输入和输出shapes,选择的尺寸将会很清晰。
'wd1' : tf.Variable(tf.truncated_normal([694, 120], mu, sigma)),
现在让我们来看看我们必须对LeNet进行的更改,将其转换为多尺度架构。首先,我们将对我们的第一个卷积图层进行二次采样。这可以通过将输出传递到Max Pooling层来轻松完成。
#Input = 14 x 14 x 6
#Output = 7 x 7 x 6
conv1_subsample = maxpooling2d(conv1)
print("1st layer shape after subsample : ", conv1_subsample.get_shape().as_list())
接下来,我们将第一个和第二个卷积层flatten。
#Input = 7 x 7 x 6
#Output = 294
conv1_subsample_shape = conv1_subsample.get_shape().as_list()
conv1_subsample_reshaped = tf.reshape(conv1_subsample, [-1, conv1_subsample_shape[1] * conv1_subsample_shape[2] * conv1_subsample_shape[3]])
#Input = 5 x 5 x 16
#Output = 400
conv2_shape = conv2.get_shape().as_list()
conv2_reshaped = tf.reshape(conv2, [-1, conv2_shape[1] * conv2_shape[2] * conv2_shape[3]])
最后,层使用连接 tf.concat
#Output = 294 + 400 = 694
concatenated_layer = tf.concat(1, [conv2_reshaped, conv1_subsample_reshaped])
print("Concatenated layer shape : ", concatenated_layer.get_shape().as_list())
TensorFlow可以很容易地将严格的前馈神经网络转换为多尺度架构。