title: How to implement the fixed length spatial pyramid pooling layer?
body: <p>I would like to implement the spatial pyramid pooling layer as introduced <a href="https://arxiv.org/pdf/1406.4729v4.pdf" rel="noreferrer">in this paper</a>. </p>
  
  <p>As the paper setting, the keypoint is to define variant kernel size and stride size of max_pooling layer, which is:</p>
  
  <pre><code>kernel_size = ceil(a/n)
  stride_size = floor(a/n)
  </code></pre>
  
  <p>where <code>a</code> is the input tensor spatial size, and <code>n</code> is the pyramid level, i.e. spatial bins of the pooling output.</p>
  
  <p>I try to implement this layer with tensorflow:</p>
  
  <pre><code>import numpy as np
  import tensorflow as tf
  
  
  def spp_layer(input_, name='SPP_layer'):
      """
      4 level SPP layer.
  
      spatial bins: [6_6, 3_3, 2_2, 1_1]
  
      Parameters
      ----------
      input_ : tensor
      name : str
  
      Returns
      -------
      tensor
      """
      shape = input_.get_shape().as_list()
  
      with tf.variable_scope(name):
  
          spp_6_6_pool = tf.nn.max_pool(input_,
                                        ksize=[1,
                                               np.ceil(shape[1]/6).astype(np.int32),
                                               np.ceil(shape[2]/6).astype(np.int32),
                                               1],
                                        strides=[1, shape[1]//6, shape[2]//6, 1],
                                        padding='SAME')
          print('SPP layer level 6:', spp_6_6_pool.get_shape().as_list())
  
          spp_3_3_pool = tf.nn.max_pool(input_,
                                        ksize=[1,
                                               np.ceil(shape[1]/3).astype(np.int32),
                                               np.ceil(shape[2]/3).astype(np.int32),
                                               1],
                                        strides=[1, shape[1]//3, shape[2]//3, 1],
                                        padding='SAME')
          print('SPP layer level 3:', spp_3_3_pool.get_shape().as_list())
  
          spp_2_2_pool = tf.nn.max_pool(input_,
                                        ksize=[1,
                                               np.ceil(shape[1]/2).astype(np.int32),
                                               np.ceil(shape[2]/2).astype(np.int32),
                                               1],
                                        strides=[1, shape[1]//2, shape[2]//2, 1],
                                        padding='SAME')
          print('SPP layer level 2:', spp_2_2_pool.get_shape().as_list())
  
          spp_1_1_pool = tf.nn.max_pool(input_,
                                        ksize=[1,
                                               np.ceil(shape[1]/1).astype(np.int32),
                                               np.ceil(shape[2]/1).astype(np.int32),
                                               1],
                                        strides=[1, shape[1]//1, shape[2]//1, 1],
                                        padding='SAME')
          print('SPP layer level 1:', spp_1_1_pool.get_shape().as_list())
  
          spp_6_6_pool_flat = tf.reshape(spp_6_6_pool, [shape[0], -1])
          spp_3_3_pool_flat = tf.reshape(spp_3_3_pool, [shape[0], -1])
          spp_2_2_pool_flat = tf.reshape(spp_2_2_pool, [shape[0], -1])
          spp_1_1_pool_flat = tf.reshape(spp_1_1_pool, [shape[0], -1])
  
          spp_pool = tf.concat(1, [spp_6_6_pool_flat,
                                   spp_3_3_pool_flat,
                                   spp_2_2_pool_flat,
                                   spp_1_1_pool_flat])
  
      return spp_pool
  </code></pre>
  
  <p>But it cannot gurantee the same length pooling output, when the input sizes are different.</p>
  
  <p>How to solve this problem?</p>