本文翻译自Using convolutional neural nets to detect facial keypoints tutorial。
用卷积神经网络检测脸部关键点的教程(一)环境配置与浅层网络训练
用卷积神经网络检测脸部关键点的教程(二)卷积神经网络训练和数据扩充
用卷积神经网络检测脸部关键点的教程(三)学习率,学习动量,dropout
用卷积神经网络检测脸部关键点的教程(四)通过前训练(pre-train)训练专项网络
上一次我们用了单隐层的神经网络,效果还可以改善,这一次就使用CNN。
卷积神经网络
上图演示了卷积操作
LeNet-5式的卷积神经网络,是计算机视觉领域近期取得的巨大突破的核心。卷积层和之前的全连接层不同,采用了一些技巧来避免过多的参数个数,但保持了模型的描述能力。这些技巧是:
1, 局部联结:神经元仅仅联结前一层神经元的一小部分。
2, 权重共享:在卷积层,神经元子集之间的权重是共享的。(这些神经元的形式被称为特征图[feature map])
3, 池化:对输入进行静态的子采样。
局部性和权重共享的图示
卷积层的单元实际上连接了前一层神经元中的一个2维patch,这个前提让网络利用了输入中的2维结构。
当使用Lasagne中的卷积层时,我们必须进行一些输入准备。输入不再像刚刚一样是一个9216像素强度的扁平向量,而是一个有着(c,0,1)形式的三维矩阵,其中c代表通道(颜色),0和1对应着图像的x和y维度。在我们的问题中,具体的三维矩阵为(1,96,96),因为我们仅仅使用了灰度一个颜色通道。
一个函数load2d对前述的load函数进行了包装,完成这个2维到三维的转变:
def load2d(test=False, cols=None):
X, y = load(test=test)
X = X.reshape(-1, 1, 96, 96)
return X, y
我们将要创建一个具有三个卷积层和两个全连接层的卷积神经网络。每个卷积层都跟着一个2*2的最大化池化层。初始卷积层有32个filter,之后每个卷积层我们把filter的数量翻番。全连接的隐层包含500个神经元。
这里还是一样没有任何形式(惩罚权重或者dropout)的正则化。事实证明当我们使用尺寸非常小的filter,如3*3或2*2,已经起到了非常不错的正则化效果。
代码如下:
net2 = NeuralNet(
layers=[
('input', layers.InputLayer),
('conv1', layers.Conv2DLayer),
('pool1', layers.MaxPool2DLayer),
('conv2', layers.Conv2DLayer),
('pool2', layers.MaxPool2DLayer),
('conv3', layers.Conv2DLayer),
('pool3', layers.MaxPool2DLayer),
('hidden4', layers.DenseLayer),
('hidden5', layers.DenseLayer),
('output', layers.DenseLayer),
],
input_shape=(None, 1, 96, 96),
conv1_num_filters=32, conv1_filter_size=(3, 3), pool1_pool_size=(2, 2),
conv2_num_filters=64, conv2_filter_size=(2, 2), pool2_pool_size=(2, 2),
conv3_num_filters=128, conv3_filter_size=(2, 2), pool3_pool_size=(2, 2),
hidden4_num_units=500, hidden5_num_units=500,
output_num_units=30,