Keras: How to use a custom pooling function for a model?

Created on 26 May 2016  Â·  8Comments  Â·  Source: keras-team/keras

I am new to Keras and trying to implement a convolution neural network for predicting handwritten digits in the MNIST dataset using the theano backend.

I tried with having a MaxPooling2D layer in my model and it gives a good result. I am planning to try on a pooling method that will give the max value and the min value on the feature map (essentially doing two poolings on the feature map). I realized that Keras uses pool2d function from theano and they don't have a implementation of a min pooling.

I am wondering is there any way to implement a custom pooling layer in Keras just like using a custom objective function?

Thanks!

Most helpful comment

Use lambda layer to customize your own layer.

def min_max_pool2d(x):
    max_x =  K.pool2d(x, pool_size=(2, 2), strides=(2, 2))
    min_x = -K.pool2d(-x, pool_size=(2, 2), strides=(2, 2))
    return K.concatenate([max_x, min_x], axis=1) # concatenate on channel

def min_max_pool2d_output_shape(input_shape):
    shape = list(input_shape)
    shape[1] *= 2
    return tuple(shape)

# replace maxpooling layer
cnn.add(Lambda(min_max_pool2d, output_shape=min_max_pool2d_output_shape))

Please try it.

All 8 comments

For this particular case, you can just do a max pool of the negation of the
input.
pool2d(x)
and pool2d(-x)

If you want other pooling there is the images2neibs that you could use:

http://deeplearning.net/software/theano/library/tensor/nnet/neighbours.html#libdoc-tensor-nnet-neighbours

On Wed, May 25, 2016 at 7:26 PM, matthewmok [email protected]
wrote:

I am new to Keras and trying to implement a convolution neural network for
predicting handwritten digits in the MNIST dataset using the theano
backend.

I tried with having a MaxPooling2D layer in my model and it gives a good
result. I am planning to try on a pooling method that will give the max
value and the min value on the feature map (essentially doing two poolings
on the feature map). I realized that Keras uses pool2d function from theano
and they don't have a implementation of a min pooling.

I am wondering is there any way to implement a custom pooling layer in
Keras just like using a custom objective function?

Thanks!

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/fchollet/keras/issues/2816

Thank you for your reply! Would you mind to provide more technical details on the implementation? I am not sure how to change the input in the tensor in the max pooling layer...

Currently, my neural net is set up as follow:

cnn.add(conv.ZeroPadding2D( (1,1), input_shape = (1,28,28), ))
cnn.add(conv.Convolution2D(nb_filters_1, nb_conv, nb_conv, activation = "relu"))
cnn.add(conv.MaxPooling2D(strides=(2,2) ))

cnn.add(conv.ZeroPadding2D((1,1)))
cnn.add(conv.Convolution2D(nb_filters_2, nb_conv, nb_conv, activation = "relu"))
cnn.add(conv.MaxPooling2D(strides=(2,2) ))

cnn.add(core.Flatten())
cnn.add(core.Dropout(0.5))
cnn.add(core.Dense(256, activation = "relu"))
cnn.add(core.Dense(nb_classes, activation = "softmax"))

cnn.summary()
cnn.compile(loss = "categorical_crossentropy", optimizer = 'adadelta', metrics = ['accuracy'])

Thanks!

Use lambda layer to customize your own layer.

def min_max_pool2d(x):
    max_x =  K.pool2d(x, pool_size=(2, 2), strides=(2, 2))
    min_x = -K.pool2d(-x, pool_size=(2, 2), strides=(2, 2))
    return K.concatenate([max_x, min_x], axis=1) # concatenate on channel

def min_max_pool2d_output_shape(input_shape):
    shape = list(input_shape)
    shape[1] *= 2
    return tuple(shape)

# replace maxpooling layer
cnn.add(Lambda(min_max_pool2d, output_shape=min_max_pool2d_output_shape))

Please try it.

Thank you for the suggestion! It works except I have to change the output_shape dimension a little since when I was using a 2-by-2 stride, the output width and height will become half.
Everything else works just perfectly and I changed the min_max_pool2D_output_shape as follow:

def min_max_pool2d_output_shape(input_shape):
    shape = list(input_shape)
    shape[1] *= 2
    shape[2] /= 2
    shape[3] /= 2
    return tuple(shape)

Thank you once again and please correct me if you catch something is wrong!

@matthewmok You are correct, I forget about the stride. LOL

Thank you for your help!

To make this work for both backends with Keras 2, it has to be

from keras import backend as K
from keras.layers.core import Lambda
from keras.layers.merge import Concatenate

def min_max_pool2d(x):
    max_x =  K.pool2d(x, pool_size=(2, 2), strides=(2, 2))
    min_x = -K.pool2d(-x, pool_size=(2, 2), strides=(2, 2))
    if K.image_dim_ordering() == 'th':
        channel = 1
    else:
        channel = -1
    return Concatenate([max_x, min_x], axis=channel)  # concatenate on channel


def min_max_pool2d_output_shape(input_shape):
    shape = list(input_shape)
    if K.image_dim_ordering() == 'th':
        shape[1] *= 2
        shape[2] /= 2
        shape[3] /= 2
    else:
        shape[3] *= 2
        shape[1] /= 2
        shape[2] /= 2
    return tuple(shape)


# replace maxpooling layer
cnn.add(Lambda(min_max_pool2d, output_shape=min_max_pool2d_output_shape))

I tried to use it instead of max pooling but i have error
TypeError: can't pickle module objects

Was this page helpful?
0 / 5 - 0 ratings