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!
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
Most helpful comment
Use lambda layer to customize your own layer.
Please try it.