<p dir="auto">MaxPool gradient of a gradient is not supported as determined in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="195147813" data-permission-text="Title is private" data-url="https://github.com/keras-team/keras/issues/4694" data-hovercard-type="issue" data-hovercard-url="/keras-team/keras/issues/4694/hovercard" href="https://github.com/keras-team/keras/issues/4694">keras-team/keras#4694</a>, which means that examples work in keras with the theano backend but not with the TensorFlow backend. I believe the relevant place where the op is registered is at <a href="https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/nn_grad.cc#L153">https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/nn_grad.cc#L153</a>.</p>
<p dir="auto">From the keras issue:</p>
<p dir="auto">I successfully ran <code class="notranslate">python mnist_cnn.py</code> from <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/keras-team/keras/commit/7e2e7a5e5a43443122df0b497f88dd77fd3bfc7c/hovercard" href="https://github.com/keras-team/keras/commit/7e2e7a5e5a43443122df0b497f88dd77fd3bfc7c">keras-team/keras@<tt>7e2e7a5</tt></a> on my GTX1080 with a TensorFlow R0.12rc0 backend. I then ran python <a href="https://github.com/fchollet/keras/blob/7e2e7a5e5a43443122df0b497f88dd77fd3bfc7c/examples/mnist_swwae.py">mnist_swwae.py</a>  and got the following failure:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="~/src/keras/examples on master
± python mnist_swwae.py
Using TensorFlow backend.
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so.8.0 locally
X_train shape: (60000, 1, 28, 28)
60000 train samples
10000 test samples
Traceback (most recent call last):
  File &quot;mnist_swwae.py&quot;, line 136, in &lt;module&gt;
    y = MaxPooling2D(pool_size=(pool_sizes[i], pool_sizes[i]))(y_prepool)
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py&quot;, line 517, in __call__
    self.add_inbound_node(inbound_layers, node_indices, tensor_indices)
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py&quot;, line 571, in add_inbound_node
    Node.create_node(self, inbound_layers, node_indices, tensor_indices)
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py&quot;, line 155, in create_node
    output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0]))
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/layers/pooling.py&quot;, line 158, in call
    dim_ordering=self.dim_ordering)
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/layers/pooling.py&quot;, line 207, in _pooling_function
    border_mode, dim_ordering, pool_mode='max')
  File &quot;/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/backend/tensorflow_backend.py&quot;, line 1853, in pool2d
    x = tf.nn.max_pool(x, pool_size, strides, padding=padding)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/nn_ops.py&quot;, line 1617, in max_pool
    name=name)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_nn_ops.py&quot;, line 1598, in _max_pool
    data_format=data_format, name=name)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py&quot;, line 759, in apply_op
    op_def=op_def)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py&quot;, line 2242, in create_op
    set_shapes_for_outputs(ret)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py&quot;, line 1617, in set_shapes_for_outputs
    shapes = shape_func(op)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py&quot;, line 1568, in call_with_requiring
    return call_cpp_shape_fn(op, require_shape_fn=True)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py&quot;, line 610, in call_cpp_shape_fn
    debug_python_shape_fn, require_shape_fn)
  File &quot;/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py&quot;, line 675, in _call_cpp_shape_fn_impl
    raise ValueError(err.message)
ValueError: Negative dimension size caused by subtracting 2 from 1 for 'MaxPool' (op: 'MaxPool') with input shapes: [?,1,32,8].
-&gt; [1]"><pre class="notranslate"><span class="pl-k">~</span>/src/keras/examples on master
± python mnist_swwae.py
Using TensorFlow backend.
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so.8.0 locally
X_train shape: (60000, 1, 28, 28)
60000 train samples
10000 <span class="pl-c1">test</span> samples
Traceback (most recent call last):
  File <span class="pl-s"><span class="pl-pds">"</span>mnist_swwae.py<span class="pl-pds">"</span></span>, line 136, <span class="pl-k">in</span> <span class="pl-k">&lt;</span>module<span class="pl-k">&gt;</span>
    y = MaxPooling2D(pool_size=(pool_sizes[i], pool_sizes[i]))(y_prepool)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py<span class="pl-pds">"</span></span>, line 517, <span class="pl-k">in</span> __call__
    self.add_inbound_node(inbound_layers, node_indices, tensor_indices)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py<span class="pl-pds">"</span></span>, line 571, <span class="pl-k">in</span> add_inbound_node
    Node.create_node(self, inbound_layers, node_indices, tensor_indices)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/engine/topology.py<span class="pl-pds">"</span></span>, line 155, <span class="pl-k">in</span> create_node
    output_tensors = to_list(outbound_layer.call(input_tensors[0], mask=input_masks[0]))
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/layers/pooling.py<span class="pl-pds">"</span></span>, line 158, <span class="pl-k">in</span> call
    dim_ordering=self.dim_ordering)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/layers/pooling.py<span class="pl-pds">"</span></span>, line 207, <span class="pl-k">in</span> _pooling_function
    border_mode, dim_ordering, pool_mode=<span class="pl-s"><span class="pl-pds">'</span>max<span class="pl-pds">'</span></span>)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/Keras-1.1.2-py2.7.egg/keras/backend/tensorflow_backend.py<span class="pl-pds">"</span></span>, line 1853, <span class="pl-k">in</span> pool2d
    x = tf.nn.max_pool(x, pool_size, strides, padding=padding)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/nn_ops.py<span class="pl-pds">"</span></span>, line 1617, <span class="pl-k">in</span> max_pool
    name=name)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/gen_nn_ops.py<span class="pl-pds">"</span></span>, line 1598, <span class="pl-k">in</span> _max_pool
    data_format=data_format, name=name)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/op_def_library.py<span class="pl-pds">"</span></span>, line 759, <span class="pl-k">in</span> apply_op
    op_def=op_def)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py<span class="pl-pds">"</span></span>, line 2242, <span class="pl-k">in</span> create_op
    set_shapes_for_outputs(ret)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py<span class="pl-pds">"</span></span>, line 1617, <span class="pl-k">in</span> set_shapes_for_outputs
    shapes = shape_func(op)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/ops.py<span class="pl-pds">"</span></span>, line 1568, <span class="pl-k">in</span> call_with_requiring
    <span class="pl-k">return</span> call_cpp_shape_fn(op, require_shape_fn=True)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py<span class="pl-pds">"</span></span>, line 610, <span class="pl-k">in</span> call_cpp_shape_fn
    debug_python_shape_fn, require_shape_fn)
  File <span class="pl-s"><span class="pl-pds">"</span>/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/common_shapes.py<span class="pl-pds">"</span></span>, line 675, <span class="pl-k">in</span> _call_cpp_shape_fn_impl
    raise ValueError(err.message)
ValueError: Negative dimension size caused by subtracting 2 from 1 <span class="pl-k">for</span> <span class="pl-s"><span class="pl-pds">'</span>MaxPool<span class="pl-pds">'</span></span> (op: <span class="pl-s"><span class="pl-pds">'</span>MaxPool<span class="pl-pds">'</span></span>) with input shapes: [<span class="pl-k">?</span>,1,32,8].
-<span class="pl-k">&gt;</span> [1]</pre></div>
<p dir="auto">Currently, neither <code class="notranslate">tf.nn.avg_pool</code> or <code class="notranslate">tf.nn.max_pool</code> support automatically taking second derivatives, making it difficult to experiment with second-order methods on neural networks that use any sort of pooling (which unfortunately includes most modern networks). Trying to take a second derivative gives a <code class="notranslate">LookupError</code>, e.g., <code class="notranslate">LookupError: No gradient defined for operation 'gradients_4...AvgPoolGrad' (op type: AvgPoolGrad)</code>.</p>
<p dir="auto">Do you have any plans for implementing second derivatives for pooling operations, or any suggested workarounds like rewriting the pooling operations in terms of elementary functions that have second derivatives defined? Thank you!</p>