【问题标题】:How to mimic Caffe's max pooling behavior in Keras/Tensorflow?如何在 Keras/Tensorflow 中模拟 Caffe 的最大池化行为?
【发布时间】:2019-01-28 13:58:15
【问题描述】:

如果我在 Keras 中有 MaxPooling2D 层和 pool_size=(2,2), strides=(2,2)。 应用于3x3 输入特征图,将产生1x1 空间输出大小。 Caffe (pool: MAX; kernel_size: 2; stride: 2) 中的相同操作将产生大小为2x2 的输出。

众所周知,Caffe 和 Tensorflow/Keras behave differently when applying max pooling.

2D 卷积有一种解决方法:为避免asymmetric padding of Conv2D in TensorFlow,可以在其前面加上explicit zero padding,并将填充类型从same 更改为valid

是否有任何类似的解决方法可以更改 Keras 中的 MaxPooling2D 行为,使其性能类似于 Caffe?更准确地说,我正在寻找一个围绕 MaxPooling2D 的包装器,它等于 Caffe 中的最大池化 2D 2x2。

也许,在MaxPooling2D 输入左上角填充一个像素?

我正在使用来自 TensorFlow 的 tf.keras。

【问题讨论】:

    标签: python tensorflow keras caffe


    【解决方案1】:

    好的,我找到了答案,我把它保存在这里。必须用零填充输入底部/右侧。这是工作的最小示例:

    import os
    import math
    import numpy as np
    
    import tensorflow as tf
    from tensorflow.python.keras.models import Model
    from tensorflow.python.keras.layers import Input, MaxPool2D
    from tensorflow.python.keras import backend as K
    
    import caffe
    from caffe.model_libs import P
    from caffe import layers as L
    from caffe.proto import caffe_pb2
    
    
    def MaxPooling2DWrapper(pool_size=(2, 2), strides=None, padding='valid', data_format=None, **kwargs):
    
        def padded_pooling(inputs):
            _, h, w, _ = K.int_shape(inputs)
            interm_input = inputs
            if h % 2 != 0 or w % 2 != 0:
                interm_input = tf.keras.layers.Lambda(lambda x: tf.pad(inputs, [[0, 0], [0, 1], [0, 1], [0, 0]]),
                                                      name='input_pad')(inputs)
            return MaxPool2D(pool_size, strides, padding, data_format, **kwargs)(interm_input)
    
        return padded_pooling
    
    
    def build_caffe_model(h, w):
        caffe_spec = caffe.NetSpec()
    
        pool_config = {                                                                                                                                                                                                                                                   
            'pool': P.Pooling.MAX,                                                                                                                                                                                                                                        
            'kernel_size': 2,                                                                                                                                                                                                                                             
            'stride': 2                                                                                                                                                                                                                                                   
        }                                                                                                                                                                                                                                                                 
    
        caffe_spec['input'] = L.Input(shape=caffe_pb2.BlobShape(dim=(1, 1, h, w)))                                                                                                                                                                                        
        caffe_spec['max_pool'] = L.Pooling(caffe_spec['input'], **pool_config)                                                                                                                                                                                            
    
        proto = str(caffe_spec.to_proto())                                                                                                                                                                                                                                
        with open('deploy.prototxt', 'w') as f:                                                                                                                                                                                                                           
            f.write(proto)                                                                                                                                                                                                                                                
        net = caffe.Net('deploy.prototxt', caffe.TEST)                                                                                                                                                                                                                    
    
        return net                                                                                                                                                                                                                                                        
    
    
    def build_keras_model(h, w):                                                                                                                                                                                                                                          
        inputs = Input(shape=(h, w, 1))                                                                                                                                                                                                                                   
    
        maxpool = MaxPooling2DWrapper()(inputs)                                                                                                                                                                                                                           
        return Model(inputs, maxpool)                                                                                                                                                                                                                                     
    
    
    def main():                                                                                                                                                                                                                                                           
        caffe.set_mode_cpu()                                                                                                                                                                                                                                              
        os.environ['GLOG_minloglevel'] = '2'                                                                                                                                                                                                                              
        h = 3                                                                                                                                                                                                                                                             
        w = 3                                                                                                                                                                                                                                                             
        size_input = h * w                                                                                                                                                                                                                                                
    
        caffe_net = build_caffe_model(h, w)                                                                                                                                                                                                                               
        keras_model = build_keras_model(h, w)                                                                                                                                                                                                                             
        keras_model.summary()                                                                                                                                                                                                                                             
    
        keras_out = keras_model.predict(np.arange(size_input).reshape(1, h, w, 1))
        caffe_net.blobs['input'].data[...] = np.arange(size_input).reshape(1, 1, h, w)
        caffe_out = caffe_net.forward()['max_pool']
    
        print('Input:')
        print(np.arange(size_input).reshape(h, w))
    
        print('Caffe result:')
        print(np.squeeze(caffe_out))
    
        print('Keras result:')
        print(np.squeeze(keras_out))
    
    
    if __name__ == '__main__':
        main()
    

    包装器仅在需要时添加填充。这段代码的输出:

    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_1 (InputLayer)         (None, 3, 3, 1)           0         
    _________________________________________________________________
    input_pad (Lambda)           (None, 4, 4, 1)           0         
    _________________________________________________________________
    max_pooling2d (MaxPooling2D) (None, 2, 2, 1)           0         
    =================================================================
    
    
    Input:
    [[0 1 2]
     [3 4 5]
     [6 7 8]]
    Caffe result:
    [[4. 5.]
     [7. 8.]]
    Keras result:
    [[4. 5.]
     [7. 8.]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-02
      • 2017-06-16
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-19
      相关资源
      最近更新 更多