卷积神经网络的研究产生了各种各样的网络模型,也提出了多个卷积层的变种,本文主要介绍卷积层的算法及在Tensorflow中的实现方法,包括:普通卷积,空洞卷积,转置卷积,分离卷积。
1. 普通卷积
以多通道输入,单卷积核(步长为1,不填充)为例说明
import tensorflow as tf
r = tf.constant([[1.,-1.,0.,2.,0],[-1.,-2.,2.,3.,1],[1.,2.,-2.,1.,0],[0.,-1.,-1.,-3.,2],[2.,0.,0.,1.,-1]])
r = tf.expand_dims(r,axis=0)
r = tf.expand_dims(r,axis=3)
print(r.shape)'''(1, 5, 5, 1)'''
wr = tf.constant([[-1., 1, 2], [1., -1, 3], [0., -1, -2]])
wr = tf.expand_dims(wr,axis=2)
wr = tf.expand_dims(wr,axis=3)
print(wr.shape)'''(3, 3, 1, 1)'''
layer = tf.nn.conv2d(r,wr,strides=1,padding='VALID')
print(layer)
'''
tf.Tensor(
[[[[ 7.]
[ 10.]
[ 3.]]
[[ -1.]
[ 24.]
[ -1.]]
[[ -5.]
[-13.]
[ 12.]]]], shape=(1, 3, 3, 1), dtype=float32)'''
import tensorflow as tf
x = tf.random.normal([2,5,5,3])
layer = tf.keras.layers.Conv2D(4,kernel_size=3,strides=1,padding='SAME')
out = layer(x)
'''
out.shape([2,5,5,4])'''
2. 空洞卷积(Dilated/Atrous Convolution)
空洞卷积在普通卷积上增加了一个dilation rate参数,用来控制感受野区域的采用步长,如下图所示。dilation rate=1时,空洞卷积退化为普通卷积。
以上面为例,dilation rate=2,实现空洞卷积
import tensorflow as tf
r = tf.constant([[1.,-1.,0.,2.,0],[-1.,-2.,2.,3.,1],[1.,2.,-2.,1.,0],[0.,-1.,-1.,-3.,2],[2.,0.,0.,1.,-1]])
r = tf.expand_dims(r,axis=0)
r = tf.expand_dims(r,axis=3)
print(r.shape)
wr = tf.constant([[-1., 1, 2], [1., -1, 3], [0., -1, -2]])
wr = tf.expand_dims(wr,axis=2)
wr = tf.expand_dims(wr,axis=3)
print(wr.shape)
layer = tf.nn.conv2d(r,wr,strides=1,padding='VALID',dilations=2)
print(layer)
'''tf.Tensor([[[[4.]]]], shape=(1, 1, 1, 1), dtype=float32)'''
import tensorflow as tf
x = tf.random.normal([2,5,5,3])
layer = tf.keras.layers.Conv2D(4,kernel_size=3,strides=1,padding='VALID',dilation_rate=2)
out = layer(x)
print(out)
'''tf.Tensor(
[[[[-2.0044637 -0.28247043 -0.06761412 0.24804944]]]
[[[-0.5734864 1.5184563 0.6989046 -1.6083945 ]]]], shape=(2, 1, 1, 4), dtype=float32)'''
3. 转置卷积
转置卷积并不是普通卷积的逆过程,但是二者之间有一定的联系,同时转置卷积也是基于普通卷积实现的。在相同的设定下,输入 经过普通卷积运算后得到𝒐 = 𝐶𝑜𝑛𝑣( ),我们将𝒐送入转置卷积运算后,得到 = 𝐶𝑜𝑛𝑣𝑇𝑟𝑎𝑛𝑠𝑝𝑜𝑠𝑒(𝒐),其中 ≠ ,但是 与 形状相同。
输入为5×5,步长为2
矩阵角度出发,转置卷积的转置是指卷积核矩阵W 产生的稀疏矩阵W′在计算过程中需要先转置W′T,
卷积核矩阵W转换为稀疏矩阵W'的过程为
通过一次矩阵相乘实现普通卷积计算:O' = W'@X'
转置卷积运算:X' = W' T@O'
import tensorflow as tf
# 创建5x5 大小的输入
x = tf.range(25)+1
x = tf.reshape(x, [1,5,5,1])
x = tf.cast(x, tf.float32)
# 创建3×3卷积核
w = tf.constant([[-1,2,-3.],[4,-5,6],[-7,8,-9]])
w = tf.expand_dims(w,axis=2)
w = tf.expand_dims(w,axis=3)
# 普通卷积运算
out = tf.nn.conv2d(x,w,strides=2,padding='VALID')
'''
tf.Tensor(
[[[[ -67.]
[ -77.]]
[[-117.]
[-127.]]]], shape=(1, 2, 2, 1), dtype=float32)'''
# 转置卷积运算
xT = tf.nn.conv2d_transpose(out,w,strides=2,padding='VALID',output_shape=[1,5,5,1])
'''
tf.Tensor(
[[[[ 67.]
[ -134.]
[ 278.]
[ -154.]
[ 231.]]
[[ -268.]
[ 335.]
[ -710.]
[ 385.]
[ -462.]]
[[ 586.]
[ -770.]
[ 1620.]
[ -870.]
[ 1074.]]
[[ -468.]
[ 585.]
[-1210.]
[ 635.]
[ -762.]]
[[ 819.]
[ -936.]
[ 1942.]
[-1016.]
[ 1143.]]]], shape=(1, 5, 5, 1), dtype=float32)'''
4. 分离卷积
普通卷积的参数量是
3 ∗ 3 ∗ 3 ∗ 4= 108
分离卷积的第一部分参数量
3 ∗ 3 ∗ 3 ∗ 1= 27
第二部分参数量
1∗ 1∗ 3 ∗4 = 12
分离卷积的总参数量只有39,但是却能实现普通卷积同样的输入输出尺寸