卷积、池化、上采样、融合、反卷积、转置卷积、图层大小与参数的计算。
1、如下代码,包含卷积、池化、上采样、融合、反卷积、转置卷积。
import keras
import numpy as np
from keras.layers import Conv2D,Dense,Flatten,BatchNormalization,Activation,Input,UpSampling2D
from keras.layers import concatenate,MaxPooling2D,Conv2DTranspose,Deconvolution2D
from keras import Model
def net(input_shape=(128,128,3)):
X = Input(input_shape)
conv1 = Conv2D(64, (3, 3), padding='same', kernel_initializer='he_normal', name='con1')(X) # 进行一次卷积
conv1 = BatchNormalization()(conv1) # 进行一次批量归一化
conv1 = Activation('relu')(conv1) # 设置激活函数
pool1 = MaxPooling2D((2, 2), name='pool1')(conv1) # 进行一次池化
up1 = UpSampling2D(size=(2, 2), name='up1')(pool1) # 进行上采样
merge1 = concatenate([conv1, up1], name='mer1', axis=-1) # 进行一次合并
deconv1 = Deconvolution2D(64, (3, 3),padding='same',kernel_initializer='he_normal',name='deconv1')(merge1) #进行一次反卷积
score1 = Conv2DTranspose(21, (3, 3), padding='same',name='score1')(deconv1) # 进行一次转置卷积
merge2 = concatenate([deconv1, score1], name='mer2', axis=-1) # 合并
model = Model(inputs=X,outputs=merge2) # 设置模型的输入与输出
model.summary() # 打印网络
net()
2、详解上述代码。
设如下表示:
图片矩阵为 W * W
卷积核大小,kernel_size:F * F
步长strides:S
边界扩充的值:P
输出图片矩阵 N * N
(1)
def net(input_shape=(128,128,3)):
X = Input(input_shape)
由以上代码可知输入的图片尺寸是128*128像数值,三通道图片。
(2)
conv1 = Conv2D(64, (3, 3), padding='same', kernel_initializer='he_normal', name='con1')(X) # 进行一次卷积
由以上代码可知进行一次卷积。
若padding=‘VALID’,则表示不在输入图片矩阵四周补零即P=0。若padding='SAME’则表示如果待输出图片比输入图片小就在其四周补零使其尺寸和输入尺寸相同。64即为卷积所得的特征图层数也可以看成通道数。
所以输出尺寸为(128,128,64)
卷积权重个数的计算:
公式:(卷积核长 x 卷积核宽 x 输入图片的通道数 + 1)x 卷积核个数
即:(3x3x3+1) * 64 = 1792
注:卷积权重个数只与卷积核的大小及Feature Map(特征图)的个数相关
(3)
conv1 = BatchNormalization()(conv1) # 进行一次批量归一化
conv1 = Activation('relu')(conv1) # 设置激活函数
由以上代码可知进行了批量归一化和设置激活函数,由于批量归一化也会产生一些参数,本人也是小白这里不太明白这些参数怎样产生的。
但是图像大小不改变。
(4)
pool1 = MaxPooling2D((2, 2), name='pool1')(conv1) # 进行一次池化
由上述代码可知进行池化。
公式:若padding=‘same’ 池化输出 N = W / S
若padding=‘VALID’ 池化输出 N = (W-F+1)/ S
即,128/2=64
(5)
up1 = UpSampling2D(size=(2, 2), name='up1')(pool1) # 进行上采样
由上述代码可知进行上采样。
公式:卷积核 =(F1, F2)输出为(width * F1,height * F2, channel)
即,(64 x 2, 64 x 2,64)= (128,128,64)
(6)
merge1 = concatenate([conv1, up1], name='mer1', axis=-1) # 进行一次合并
由上述代码可知进行按axis=-1方向合并,个人感觉叫堆叠比较合适。
因为时按axis=-1,所以图片尺寸不变,在通道数上堆叠。
即,64+64=128,(128, 128, 128)
(7)
deconv1 = Deconvolution2D(64,(3,3),padding='same',kernel_initializer='he_normal',name='deconv1')(merge1) #进行一次反卷积
由上述代码可知进行一次反卷积。
即,64+64=128,(128, 128, 128)
图片尺寸公式:反卷积输出大小 N =(W-1)* S - 2P + F
即,N = (128-1)* 1-2+3 = 128
权重个数公式:(卷积核长 x 卷积核宽 x 输入图片的通道数 + 1)x 卷积核个数
即,(3 x 3 x 128 +1)x 64 = 73792
(8)
score1 = Conv2DTranspose(21, (3, 3), padding='same',name='score1')(deconv1) # 进行一次转置卷积
由上述代码可知进行一次转置卷积。
图片尺寸公式:转置卷积输出大小 N =(W-1)* S - 2P + F
即,N = (128-1)* 1-2+3 = 128
权重个数公式:(卷积核长 x 卷积核宽 x 输入图片的通道数 + 1)x 卷积核个数
即,(3 x 3 x 64 +1)x 21 = 12117
(9)
merge2 = concatenate([deconv1, score1], name='mer2', axis=-1) # 合并
由上述代码可知进行按axis=-1方向堆叠。
因为时按axis=-1,所以图片尺寸不变,在通道数上堆叠。
即,64+21=85,(128, 128, 128)
3、程序运行验证。
Model: "model_1"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
Ran 0 tests in 0.000s
input_1 (InputLayer) (None, 128, 128, 3) 0
__________________________________________________________________________________________________
con1 (Conv2D) (None, 128, 128, 64) 1792 input_1[0][0]
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 128, 128, 64) 256 con1[0][0]
__________________________________________________________________________________________________
activation_1 (Activation) (None, 128, 128, 64) 0 batch_normalization_1[0][0]
__________________________________________________________________________________________________
pool1 (MaxPooling2D) (None, 64, 64, 64) 0 activation_1[0][0]
__________________________________________________________________________________________________
up1 (UpSampling2D) (None, 128, 128, 64) 0 pool1[0][0]
__________________________________________________________________________________________________
mer1 (Concatenate) (None, 128, 128, 128) 0 activation_1[0][0] up1[0][0]
__________________________________________________________________________________________________
deconv1 (Conv2DTranspose) (None, 128, 128, 64) 73792 mer1[0][0]
__________________________________________________________________________________________________
score1 (Conv2DTranspose) (None, 128, 128, 21) 12117 deconv1[0][0]
__________________________________________________________________________________________________
mer2 (Concatenate) (None, 128, 128, 85) 0 deconv1[0][0] score1[0][0]
==================================================================================================
Total params: 87,957
Trainable params: 87,829
Non-trainable params: 128
__________________________________________________________________________________________________
4、补充:如何设置反卷积的参数,使反卷积后的图像大小恰好是卷积前的2倍、4倍、8倍。
注:反卷积就是转置卷积且反卷积有两种一是Deconvolution2D、二是Conv2DTranspose。
如果想实现放大为f(偶数)通常的设置为:
F= 2f
S = f
P = f/2
输出大小计算公式:
N = (W-1)*S-2P+F
例如:输入(64, 64, 3),想要输出为(128,128,3),即扩大2倍,F、S、P该如下求法,
128 = (64 - 1)x f - 2 x f/2 + 2f
解得:f = 2
所以,F = 4、S = 2、P = 1