卷积 tf.nn.conv2d
- 普通卷积
- 空洞卷积
- 卷积函数
普通卷积
Padding 方式(边缘填充方式)有两种:
- SAME :在边缘补充0
- VALID:不做任何填补,当有剩余项时,VALID采用的方式是“丢弃”。
采用 SAME 的 padding 方式相比 VALID 的优势是,可以充分利用输入的数据,把所有信息都加入运算。所以大部分时候,使用卷积时Padding 方式都是 SAME。
Stride(步长):
需要在四个维度上 [batch, height, width, channel] 设置Stride, 但是常见的设置只有一种: width 和 height 上的Stride >= 1, batch 和 channel 维度上的Stride=1
例子1:
input=3 x 3, padding=SAME, stride=1
例子2:
input=3 x 3, padding=SAME, stride=2
例子3:
input=4 x 4, padding=SAME, stride=2
在只需要补一行一列的情况下,TensorFlow 的填补方式是右侧和下侧补0。
例子4:
input=4 x 4, padding=VALID, stride=2
当有剩余项时,VALID采用的方式是“丢弃”。
例子5: 多通道输入 与 多通道输出
之前的例子都是输入通道数为1,输出通道数也为1,但是实际应用是,大部分时候都是多通道输入切多通道输出。
此例子中,已知input shape = (3, 3, 2), 我们想要得到 output shape 也为 (3, 3, 2),于是有以下的卷积设计:
- input shape = (3, 3, 2) # [height, width, channel]
- filter shape = (3, 3, 2, 2) # [height, width, input_channel, output_channel]
- padding=‘SAME’
- stride=1
- output shape = (3, 3, 2) # [height, width, channel]
空洞卷积
在对某个channel选择卷机区域时,普通卷积所选择的区域是连续的。而空洞卷积选择的区域则不是连续的一块区域。
空洞卷积元素之间的距离由参数 dilations 指定。由 dilations 的复数形式便可知,其可以在多个维度设置 dilation, 不仅 height 和 width 维度可设置,在batch 和 channel 为维度上也可设置,但是一般batch 和 channel维度上的dilation=1。默认情况是 dilations=[1, 1, 1, 1]。
计算如下:
卷积函数
函数原型:
tf.nn.conv2d(
input,
filter,
strides,
padding,
use_cudnn_on_gpu=True,
data_format='NHWC',
dilations=[1, 1, 1, 1],
name=None
)
参数:
- input:输入数据,四维tensor对象,维度格式可以是[batch, height, width, channel],或者[batch, channel, height, width], 具体方式由参数 data_format 决定。
- filter:卷积核, 四维tensor对象,数据维度格式为[fiter_height, fiter_width, input_channel, output_channel]
- strides: 是一个一维列表,长度为4, 代表每个维度的stride,具体维度顺序由参数 data_format 决定
- padding:只能取 SAME 或者 VALID
- use_cudnn_on_gpu=True:表示GPU是否使用cuda库
- data_format=‘NHWC’: 只能取 ‘NHWC’ ,或者 ‘NCWH’
- dilations=[1, 1, 1, 1]: 是一个一维列表,长度为4,空洞卷积在每个维度的步长,默认为[1, 1, 1, 1]
举例:
import tensorflow as tf
# input_shape = [C, W, H]
input_data = [[[1, 2, 3],
[2, 1, 3],
[3, 2, 1]]]
# input_shape = [input_channel;, width, height]
weight_data = [[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]]
const_input = tf.constant(input_data, dtype=tf.float32)
const_weight = tf.constant(weight_data, dtype=tf.float32)
input = tf.Variable(const_input, name='input')
input = tf.transpose(input, perm=[1, 2, 0])
input = tf.expand_dims(input, dim=0)
weight = tf.Variable(const_weight, name='weight')
weight = tf.transpose(weight, perm=[1, 2, 0])
weight = tf.expand_dims(weight, dim=3)
conv = tf.nn.conv2d(input, weight, strides=[1, 1, 1, 1], padding='SAME', dilations=[1, 1, 1, 1])
result = weight = tf.transpose(conv[0], perm=[2, 0, 1])
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
conv_val = sess.run(result)
print(conv_val)
# 输出为:
# [[[ 6. 12. 9.]
# [11. 18. 12.]
# [ 8. 12. 7.]]]