卷积
首先定义本文要用到的符号
- 输入图片的大小: i1=i2=ii1=i2=i。
- 卷积核的大小: k1=k2=kk1=k2=k。
- 卷积步长:s1=s2=ss1=s2=s。
- 填充padding=ppadding=p。
下图表示参数为(i=5,k=3,s=2,p=1)(i=5,k=3,s=2,p=1)的卷积计算过程,可以看出输出的图片大小是(3∗3)(3∗3)。
下图是参数为(i=6,k=3,s=2,p=1)(i=6,k=3,s=2,p=1)的卷积计算过程,输出大小为(3∗3)(3∗3)。
当步长s=1时,可按照卷积过程逆向计算大小。
# -*- coding: utf-8 -*-
# @Time : 2017/11/16 20:18
# @File : Deconv2d.py
# @Author : Zhiwei Zhong
# @Function : 反卷积转置卷积
import tensorflow as tf
import numpy as np
x1 = tf.Variable(np.random.normal(0, 1, 3*3).reshape(1, 3, 3, 1), dtype=tf.float32)
# x2 shape=(1, 6, 6, 3)数字代表的含义分别是(batch, 行数, 列数,通道数)
x2 = tf.Variable(np.random.normal(0, 1, 6*6*3).reshape(1, 6, 6, 3), dtype=tf.float32)
x3 = tf.Variable(np.random.normal(0, 1, 5*5*3).reshape(1, 5, 5, 3), dtype=tf.float32)
# 卷积核的 shape 含义为(滤波器的行, 滤波器的列, 当前层的深度, 滤波器的深度)滤波器的深度也是输出层的深度
kernel = tf.Variable(np.random.normal(0, 1, 3*3*3).reshape(3, 3, 3, 1), dtype=tf.float32)
# 6*6*3 -> 3*3*1
y2 = tf.layers.conv2d(x3, 1, 3, strides=2, padding='SAME')
# 5*5*3 -> 3*3*1
y3 = tf.layers.conv2d(x2, 1, 3, strides=2, padding="SAME")
# 相同的卷积参数下,6*6*3和5*5*3都能得到 3*3*1的结果,如果用下面这个函数他计算出的结果是不需要取整的那一个,如果
# 要规定输出的大小,可以用nn.conv2d_transpose()函数。
z2 = tf.layers.conv2d_transpose(y3, 1, 3, strides=2, padding="SAME")
# strides 第一维和最后一维必须是1, 中间两个代表横着和竖向每次卷积跨过的幅度。
z3 = tf.nn.conv2d_transpose(y2, filter=kernel, strides=[1, 2, 2, 1], output_shape=[1, 5, 5, 3], padding="SAME")
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(y2).shape)
print(sess.run(y3).shape)
print(sess.run(z2).shape)
print(sess.run(z3).shape)
"""
(1, 3, 3, 1)
(1, 3, 3, 1)
(1, 6, 6, 1)
(1, 5, 5, 3)
"""