Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use a custom pooling function for a model? #2816

Closed
matthewmok opened this issue May 25, 2016 · 8 comments
Closed

How to use a custom pooling function for a model? #2816

matthewmok opened this issue May 25, 2016 · 8 comments

Comments

@matthewmok
Copy link
Contributor

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!

@nouiz
Copy link
Contributor

nouiz commented May 26, 2016

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 notifications@github.com
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
#2816

@matthewmok
Copy link
Contributor Author

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!

@joelthchao
Copy link
Contributor

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.

@matthewmok
Copy link
Contributor Author

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!

@joelthchao
Copy link
Contributor

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

@matthewmok
Copy link
Contributor Author

Thank you for your help!

@MartinThoma
Copy link
Contributor

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))

@ngragaei
Copy link

ngragaei commented Mar 8, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants