1.残差连接
残差连接( residual connection)是一种常见的类图网络组件,在 2015 年之后的许多网络架构(包括 Xception)中都可以见到。 2015 年末,来自微软的何恺明等人在 ILSVRC ImageNet 挑战赛中获胜,其中引入了这一方法。残差连接解决了困扰所有大规模深度学习模型的两个共性问题:梯度消失和表示瓶颈。通常来说,向任何多于 10 层的模型中添加残差连接,都可能会有所帮助。
残差连接是让前面某层的输出作为后面某层的输入,从而在序列网络中有效地创造了一条
捷径。前面层的输出没有与后面层的激活连接在一起,而是与后面层的激活相加(这里假设两个激活的形状相同)。如果它们的形状不同,我们可以用一个线性变换将前面层的激活改变成目标形状(例如,这个线性变换可以是不带激活的 Dense 层;对于卷积特征图,可以是不带激活1× 1 卷积)。
from keras import layers
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.add([y, x])
from keras import layers
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.MaxPooling2D(2, strides=2)(y)
residual = layers.Conv2D(128, 1, strides=2, padding='same')(x)
y = layers.add([y, residual])
2.批标准化
标准化( normalization)是一大类方法,用于让机器学习模型看到的不同样本彼此之间更加相似,这有助于模型的学习与对新数据的泛化。最常见的数据标准化形式就是多次见到的那种形式:将数据减去其平均值使其中心为 0,然后将数据除以其标准差使其标准差为 1。实际上,这种做法假设数据服从正态分布(也叫高斯分布), 并确保让该分布的中心为 0,同时缩放到方差为 1。
conv_model.add(layers.Conv2D(32, 3, activation='relu'))
conv_model.add(layers.BatchNormalization())
dense_model.add(layers.Dense(32, activation='relu'))
dense_model.add(layers.BatchNormalization())
BatchNormalization 层接收一个 axis 参数,它指定应该对哪个特征轴做标准化。这个参数的默认值是 -1,即输入张量的最后一个轴。对于 Dense 层、 Conv1D 层、 RNN 层和将data_format 设为 “channels_last”(通道在后)的 Conv2D 层,这个默认值都是正确的。但有少数人使用将 data_format 设为 “channels_first”(通道在前)的 Conv2D 层,这时特征轴是编号为 1 的轴,因此 BatchNormalization 的 axis 参数应该相应地设为 1。
3.深度可分离卷积
深度可分离卷积( depthwise separable convolution)层( SeparableConv2D)的作用。这个层对输入的每个通道分别执行空间卷积,然后通过逐点卷积( 1× 1 卷积)将输出通道混合。这相当于将空间特征学习和通道特征学习分开,如果你假设输入中的空间位置高度相关,但不同的通道之间相对独立,那么这么做是很有意义的。它需要的参数要少很多,计算量也更小,因此可以得到更小、更快的模型。因为它是一种执行卷积更高效的方法,所以往往能够使用更少的数据学到更好的表示,从而得到性能更好的模型。
from keras.models import Sequential, Model
from keras import layers
height = 64
width = 64
channels = 3
num_classes = 10
model = Sequential()
model.add(layers.SeparableConv2D(32, 3,
activation='relu',
input_shape=(height, width, channels,)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
参考书籍:《python深度学习》