class_docstr: Spatial Pyramid Pooling Layer
  
  Performs spatial pyramid pooling (SPP) over the input.
  It will turn a 2D input of arbitrary size into an output of fixed
  dimension.
  Hence, the convolutional part of a DNN can be connected to a dense part
  with a fixed number of nodes even if the dimensions of the
  input image are unknown.
  
  The pooling is performed over :math:`l` pooling levels.
  Each pooling level :math:`i` will create :math:`M_i` output features.
  :math:`M_i` is given by :math:`n_i * n_i`,
  with :math:`n_i` as the number of pooling operation per dimension in
  level :math:`i`, and we use a list of the :math:`n_i`'s as a
  parameter for SPP-Layer.
  The length of this list is the level of the spatial pyramid.
  
  Parameters
  ----------
  incoming : a :class:`Layer` instance or tuple
      The layer feeding into this layer, or the expected input shape.
  
  pool_dims : list of integers
      The list of :math:`n_i`'s that define the output dimension of each
      pooling level :math:`i`. The length of pool_dims is the level of
      the spatial pyramid.
  
  mode : string
      Pooling mode, one of 'max', 'average_inc_pad', 'average_exc_pad'
      Defaults to 'max'.
  
  implementation : string
      Either 'fast' or 'kaiming'. The 'fast' version uses theano's pool_2d
      operation, which is fast but does not work for all input sizes.
      The 'kaiming' mode is slower but implements the pooling as described
      in [1], and works with any input size.
  
  **kwargs
      Any additional keyword arguments are passed to the :class:`Layer`
      superclass.
  
  Notes
  -----
  This layer should be inserted between the convolutional part of a
  DNN and its dense part. Convolutions can be used for
  arbitrary input dimensions, but the size of their output will
  depend on their input dimensions. Connecting the output of the
  convolutional to the dense part then usually demands us to fix
  the dimensions of the network's InputLayer.
  The spatial pyramid pooling layer, however, allows us to leave the
  network input dimensions arbitrary. The advantage over a global
  pooling layer is the added robustness against object deformations
  due to the pooling on different scales.
  
  References
  ----------
  .. [1] He, Kaiming et al (2015):
         Spatial Pyramid Pooling in Deep Convolutional Networks
         for Visual Recognition.
         http://arxiv.org/pdf/1406.4729.pdf.
class_docstr_tok: ["Spatial","Pyramid","Pooling","Layer","Performs","spatial","pyramid","pooling","(","SPP",")","over","the","input",".","It","will","turn","a","2D","input","of","arbitrary","size","into","an","output","of","fixed","dimension",".","Hence",",","the","convolutional","part","of","a","DNN","can","be","connected","to","a","dense","part","with","a","fixed","number","of","nodes","even","if","the","dimensions","of","the","input","image","are","unknown",".","The","pooling","is","performed","over",":","math",":","`","l","`","pooling","levels",".","Each","pooling","level",":","math",":","`","i","`","will","create",":","math",":","`","M_i","`","output","features",".",":","math",":","`","M_i","`","is","given","by",":","math",":","`","n_i","*","n_i","`",",","with",":","math",":","`","n_i","`","as","the","number","of","pooling","operation","per","dimension","in","level",":","math",":","`","i","`",",","and","we","use","a","list","of","the",":","math",":","`","n_i","`","'s","as","a","parameter","for","SPP-Layer",".","The","length","of","this","list","is","the","level","of","the","spatial","pyramid",".","Parameters","--","--","--","--","--","incoming",":","a",":","class",":","`","Layer","`","instance","or","tuple","The","layer","feeding","into","this","layer",",","or","the","expected","input","shape",".","pool_dims",":","list","of","integers","The","list","of",":","math",":","`","n_i","`","'s","that","define","the","output","dimension","of","each","pooling","level",":","math",":","`","i","`",".","The","length","of","pool_dims","is","the","level","of","the","spatial","pyramid",".","mode",":","string","Pooling","mode",",","one","of","'max","'",",","'average_inc_pad","'",",","'average_exc_pad'","Defaults","to","'max","'",".","implementation",":","string","Either","'fast","'","or","'kaiming","'",".","The","'fast","'","version","uses","theano","'s","pool_2d","operation",",","which","is","fast","but","does","not","work","for","all","input","sizes",".","The","'kaiming","'","mode","is","slower","but","implements","the","pooling","as","described","in","[","1","]",",","and","works","with","any","input","size",".","*","*","kwargs","Any","additional","keyword","arguments","are","passed","to","the",":","class",":","`","Layer","`","superclass",".","Notes","--","--","-","This","layer","should","be","inserted","between","the","convolutional","part","of","a","DNN","and","its","dense","part",".","Convolutions","can","be","used","for","arbitrary","input","dimensions",",","but","the","size","of","their","output","will","depend","on","their","input","dimensions",".","Connecting","the","output","of","the","convolutional","to","the","dense","part","then","usually","demands","us","to","fix","the","dimensions","of","the","network","'s","InputLayer",".","The","spatial","pyramid","pooling","layer",",","however",",","allows","us","to","leave","the","network","input","dimensions","arbitrary",".","The","advantage","over","a","global","pooling","layer","is","the","added","robustness","against","object","deformations","due","to","the","pooling","on","different","scales",".","References","--","--","--","--","--","..","[","1","]","He",",","Kaiming","et","al","(","2015",")",":","Spatial","Pyramid","Pooling","in","Deep","Convolutional","Networks","for","Visual","Recognition",".","http",":","\/\/arxiv.org\/pdf\/1406.4729.pdf","."]
code: def __init__(
      self,
      incoming,
      pool_dims=[4, 2, 1],
      mode="max",
      implementation="fast",
      **kwargs,
  ):
      super(SpatialPyramidPoolingLayer, self).__init__(
          incoming, **kwargs
      )
      if len(self.input_shape) != 4:
          raise ValueError(
              "Tried to create a SPP layer with "
              "input shape %r. Expected 4 input dimensions "
              "(batchsize, channels, 2 spatial dimensions)."
              % (self.input_shape,)
          )
  
      if implementation != "kaiming":  # pragma: no cover
          # Check if the running theano version supports symbolic
          # variables as arguments for pool_2d. This is required
          # unless using implementation='kaiming'
          try:
              pool_2d(
                  T.tensor4(),
                  ws=T.ivector(),
                  stride=T.ivector(),
                  ignore_border=True,
                  pad=None,
              )
          except ValueError:
              raise ImportError(
                  "SpatialPyramidPoolingLayer with "
                  "implementation='%s' requires a newer "
                  "version of theano. Either update "
                  "theano, or use implementation="
                  "'kaiming'" % implementation
              )
  
      self.mode = mode
      self.implementation = implementation
      self.pool_dims = pool_dims
  
imports: import theano.tensor
  from .base import Layer
  from ..utils import as_tuple
label_desc: Use image node_id 1 to create a new SpatialPyramidPoolingLayer object from inherited base classes: Layer with example: obj = SpatialPyramidPoolingLayer(incoming, pool_dims, mode, implementation)