Keras
MinimumPooling
Deep Learning
Neural Networks
Machine Learning

MinimumPooling in Keras

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Keras includes MaxPooling and AveragePooling, but it does not ship a built-in MinimumPooling layer. When you need the smallest value from each spatial window, the practical solution is to build the behavior yourself from TensorFlow primitives rather than looking for a missing high-level layer.

Core Sections

What minimum pooling actually computes

Pooling reduces a feature map by summarizing local neighborhoods. Max pooling keeps the largest activation in each window. Average pooling keeps the mean. Minimum pooling keeps the smallest value.

For a 2 x 2 window like this:

text
5  2
7  3

minimum pooling returns 2.

That makes it useful only in fairly specific cases. In standard vision models, max pooling is far more common because it preserves strong activations. Minimum pooling emphasizes local low responses, so it is better suited to specialized signal-processing tasks, conservative mask reductions, or morphology-like operations.

The simplest implementation uses negative max pooling

The key identity is straightforward: the minimum of a set is the negative of the maximum of the negated set. In other words:

  • 'min(x) equals -max(-x)'

That means you can implement minimum pooling with TensorFlow’s existing max-pooling operation.

python
1import tensorflow as tf
2
3
4def min_pool2d(inputs, pool_size=(2, 2), strides=(2, 2), padding="VALID"):
5    return -tf.nn.max_pool2d(
6        -inputs,
7        ksize=pool_size,
8        strides=strides,
9        padding=padding,
10    )
11
12
13x = tf.constant(
14    [[[[5.0], [2.0]], [[7.0], [3.0]]]],
15    dtype=tf.float32,
16)
17
18print(min_pool2d(x).numpy())

This is the core idea behind most custom Keras solutions. It works because tf.nn.max_pool2d already handles efficient window traversal and supports gradient propagation.

Wrap it in a custom Keras layer

If the operation will appear in more than one place, a custom layer is cleaner than repeating a helper function. It also integrates better with model summaries and configuration.

python
1import tensorflow as tf
2
3
4class MinPooling2D(tf.keras.layers.Layer):
5    def __init__(self, pool_size=(2, 2), strides=None, padding="VALID", **kwargs):
6        super().__init__(**kwargs)
7        self.pool_size = pool_size
8        self.strides = strides or pool_size
9        self.padding = padding.upper()
10
11    def call(self, inputs):
12        return -tf.nn.max_pool2d(
13            -inputs,
14            ksize=self.pool_size,
15            strides=self.strides,
16            padding=self.padding,
17        )
18
19    def get_config(self):
20        config = super().get_config()
21        config.update(
22            {
23                "pool_size": self.pool_size,
24                "strides": self.strides,
25                "padding": self.padding,
26            }
27        )
28        return config

The get_config method matters if you plan to save and reload the model. Without it, serializing the layer becomes harder.

Using the layer inside a model

Once wrapped, the layer behaves like any other Keras component.

python
1import tensorflow as tf
2
3inputs = tf.keras.Input(shape=(28, 28, 1))
4x = tf.keras.layers.Conv2D(8, kernel_size=3, activation="relu")(inputs)
5x = MinPooling2D(pool_size=(2, 2))(x)
6x = tf.keras.layers.Flatten()(x)
7outputs = tf.keras.layers.Dense(10, activation="softmax")(x)
8
9model = tf.keras.Model(inputs=inputs, outputs=outputs)
10model.summary()

This works because the custom layer is still composed of differentiable TensorFlow ops. Training, backpropagation, and model export all continue to function normally.

Shapes, padding, and where this layer fits

Output shape rules are exactly the same as for max pooling because the underlying operation is still tf.nn.max_pool2d. pool_size, strides, and padding control the result dimensions.

The design question is not shape compatibility but whether minimum pooling makes semantic sense for the model. In image classification, it often suppresses the strongest features and hurts performance. In tasks where low local values carry meaning, it can be useful.

A quick rule is this: if max pooling helps capture the presence of features, minimum pooling helps capture the presence of low-valued regions. Those are not interchangeable goals.

Common Pitfalls

  • Looking for a built-in tf.keras.layers.MinPooling2D wastes time because Keras does not provide one.
  • Forgetting the double negation produces ordinary max pooling instead of minimum pooling.
  • Omitting get_config in a reusable custom layer makes serialization and reload workflows harder.
  • Using minimum pooling in a vision model without a data-driven reason often degrades accuracy because it preserves the weakest activation in each window.
  • Passing inconsistent padding, pool_size, or strides values causes the same shape issues you would see with any other pooling layer.

Summary

  • Keras has no native minimum-pooling layer, but TensorFlow primitives are enough to build one.
  • The standard implementation is negative max pooling on negated inputs.
  • A custom Layer class is the cleanest approach for reusable models.
  • Output shape behavior follows the same rules as max pooling.
  • Minimum pooling is specialized and should be chosen because the data semantics require it, not as a generic alternative to max pooling.

Course illustration
Course illustration

All Rights Reserved.