最大池化和平均池化的混合

hybrid of max pooling and average pooling

在使用 Keras(使用 TensorFlow 后端)调整深度卷积网络时,我想尝试 MaxPooling2DAveragePooling2D 之间的混合,因为这两种策略似乎改善了两个不同的方面我的 objective.

我在想这样的事情:

    -------
    |8 | 1|
x = ---+---
    |1 | 6|
    -------

average_pooling(x)                ->   4
max_pooling(x)                    ->   8
hybrid_pooling(x, alpha_max=0.0)  ->   4
hybrid_pooling(x, alpha_max=0.25) ->   5
hybrid_pooling(x, alpha_max=0.5)  ->   6
hybrid_pooling(x, alpha_max=0.75) ->   7
hybrid_pooling(x, alpha_max=1.0)  ->   8

或者作为一个等式:

hybrid_pooling(x, alpha_max) =
    alpha_max * max_pooling(x) + (1 - alpha_max) * average_pooling(x)

既然这样的东西好像没有现成的,那如何才能高效的实现呢?

我现在使用不同的解决方案来组合两种池化变体。

  • 将张量赋予两个池化函数
  • 连接结果
  • 使用一个小的 conv 层来学习如何组合

当然,这种方法的计算成本更高,但也更灵活。 串联后的卷积层可以学习简单地将两个池化结果与一个 alpha 混合,但它最终也可以对不同的特征使用不同的 alpha,当然——正如卷积层所做的那样——以一种全新的方式组合池化特征。

代码(Keras 函数 API)如下所示:

import numpy as np
from tensorflow.keras.layers import Input, MaxPooling2D, Conv2D
from tensorflow.keras.layers import Concatenate, AveragePooling2D
from tensorflow.keras.models import Model

# implementation of the described custom pooling layer
def hybrid_pool_layer(pool_size=(2,2)):
    def apply(x):
        return Conv2D(int(x.shape[-1]), (1, 1))(
            Concatenate()([
                MaxPooling2D(pool_size)(x),
                AveragePooling2D(pool_size)(x)]))
    return apply

# usage example
inputs = Input(shape=(256, 256, 3))
x = inputs
x = Conv2D(8, (3, 3))(x)
x = hybrid_pool_layer((2,2))(x)
model = Model(inputs=inputs, outputs=x)
model.compile(loss='categorical_crossentropy', optimizer='nadam')

当然也可以省去 Conv2D 和 return 两个池的串联,让下一层进行合并工作。但是上面的实现确保了这种混合池化产生的张量具有正常的单一池化操作所期望的形状。

此处是 alpha * average_pooling(x) + (1 - alpha) * max_pooling(x) 的简单实现,可放入网络中...

x = Conv2D(32, 3, activation='relu')(...)
a = AveragePooling2D()(x)
a = Lambda(lambda xx : xx*alpha)(a)
m = MaxPooling2D()(x)
m = Lambda(lambda xx : xx*(1-alpha))(m)
x = Add()([a,m])

alpha = 0.xx 在 [0,1]

范围内