1. 池化定义
通常来说卷积之后的图像虽然在尺寸上有所减小,但是其尺寸还是较大,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特定特征的平均值 (或最大值)。这些概要统计特征不仅具有低得多的维度 (相比使用所有提取得到的特征),同时还会改善结果(不容易过拟合)。这种聚合的操作就叫做池化 (pooling),有时也称为平均池化或者最大池化 (取决于计算池化的方法)。
池化的不变性:如果人们选择图像中的连续范围作为池化区域,并且只是池化相同(重复)的隐藏单元产生的特征,那么,这些池化单元就具有平移不变性 (translation invariant)。这就意味着即使图像经历了一个小的平移之后,依然会产生相同的 (池化的) 特征。使得网络具有了一定的鲁棒性。
下面一幅图就是对池化层的形象描述。
池化层之后的矩阵数据一般会大小减半,但是其减半的方式也主要有两种Max-Pooling和Average-Pooling。
2. 池化层正向传播
2.1 Max-Pooling
该种类型的池化层是取运算窗口中的最大值作为最后运算的结果,可以表示为:
上图中就是以 3∗2 3 ∗ 2 大小的窗口进行运算得到的结果
2.2 Average-Pooling
该种类型的池化层是取运算窗口中的所有值的均值作为最后运算的结果,可以表示为:
2.3 Caffe代码
template <typename Dtype>
void PoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top) {
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
const int top_count = top[0]->count();
// We'll output the mask to top[1] if it's of size >1.
const bool use_top_mask = top.size() > 1;
int* mask = NULL; // suppress warnings about uninitalized variables
Dtype* top_mask = NULL;
// Different pooling methods. We explicitly do the switch outside the for
// loop to save time, although this results in more code.
switch (this->layer_param_.pooling_param().pool()) {