...
1..讲解
卷积:conv2
In this example:
- Input width = 13
- Filter width = 6
- Stride = 5
"VALID"
only ever drops the right-most columns (or bottom-most rows).
"SAME"
tries to pad evenly left and right, but if the amount of columns to be added is odd, it will add the extra column to the right, as is the case in this example (the same logic applies vertically: there may
be an extra row of zeros at the bottom).
The
TensorFlow Convolution example gives an overview about the difference betweenSAME
andVALID
:
-
For the SAME
padding, the output height and width are computed as:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
And
-
For the VALID
padding, the output height and width are computed as:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
池化:max_pool
I'll give an example to make it clearer:
x
: input image of shape [2, 3], 1 channel
valid_pad
: max pool with 2x2 kernel, stride 2 and VALID padding.
same_pad
: max pool with 2x2 kernel, stride 2 and SAME padding (this is theclassic way to go)
The output shapes are:
valid_pad
: here, no padding so the output shape is [1, 1]
same_pad
: here, we pad the image to the shape [2, 4] (with-inf
and then apply max pool), so the output shape is [1, 2]
x = tf.constant([[1., 2., 3.],
[4., 5., 6.]])
x = tf.reshape(x, [1, 2, 3, 1]) # give a shape accepted by tf.nn.max_pool
valid_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='VALID')
same_pad = tf.nn.max_pool(x, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
valid_pad.get_shape() == [1, 1, 1, 1] # valid_pad is [5.]
same_pad.get_shape() == [1, 1, 2, 1] # same_pad is [5., 6.]
2.示例+讲解
输出5×5的feature map
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,1]))
-
-
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
6.如果卷积核有多个
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
此时输出7张5×5的feature map
7.步长不为1的情况,文档里说了对于图片,因为只有两维,通常strides取[1,stride,stride,1]
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
此时,输出7张3×3的feature map
-
x.x.x
-
.....
-
x.x.x
-
.....
-
x.x.x
8.如果batch值不为1,同时输入10张图
-
input = tf.Variable(tf.random_normal([10,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
每张图,都有7张3×3的feature map,输出的shape就是[10,3,3,7]
最后,把程序总结一下:
-
import tensorflow as tf
-
#case 2
-
input = tf.Variable(tf.random_normal([1,3,3,5]))
-
filter = tf.Variable(tf.random_normal([1,1,5,1]))
-
-
op2 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
-
#case 3
-
input = tf.Variable(tf.random_normal([1,3,3,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,1]))
-
-
op3 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
-
#case 4
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,1]))
-
-
op4 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID')
-
#case 5
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,1]))
-
-
op5 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
-
#case 6
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op6 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
-
#case 7
-
input = tf.Variable(tf.random_normal([1,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op7 = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
-
#case 8
-
input = tf.Variable(tf.random_normal([10,5,5,5]))
-
filter = tf.Variable(tf.random_normal([3,3,5,7]))
-
-
op8 = tf.nn.conv2d(input, filter, strides=[1, 2, 2, 1], padding='SAME')
-
-
init = tf.initialize_all_variables()
-
with tf.Session() as sess:
-
sess.run(init)
-
print("case 2")
-
print(sess.run(op2))
-
print("case 3")
-
print(sess.run(op3))
-
print("case 4")
-
print(sess.run(op4))
-
print("case 5")
-
print(sess.run(op5))
-
print("case 6")
-
print(sess.run(op6))
-
print("case 7")
-
print(sess.run(op7))
-
print("case 8")
-
print(sess.run(op8))
因为是随机初始化,我的结果是这样的: