Reputation: 835
I want to define my custom pooling layer, instead of returning the max values like the MaxPooling layer, it would output the k maximum values and the k minimum values.
I am using Tensorflow as the backend. I need the output vector to be sorted.
I was thinking about doing that:
from keras.layers.pooling import _Pooling1D
class MinMaxPooling1D(_Pooling1D):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MinMaxPooling1D, self).__init__(**kwargs)
def _pooling_function(self, inputs, **kwargs):
sorted_ = tf.contrib.framework.sort(inputs, axis = -1)
print(sorted_)
return np.concatenate((sorted_[:,:,:self.output_dim/2], sorted_[:,:,-self.output_dim/2:]))
But then I get:
Tensor("min_max_pooling1d_1/sort/Neg_1:0", shape=(?, 1, 1, ?), dtype=float32)
ValueError: zero-dimensional arrays cannot be concatenated
The MinMaxPooling1D layer is applied to a (None, 1, 10) shape output.
I was then thinking about adding a Flatten layer before the MinMaxPooling1D one, but then there is a dimension issue:
ValueError: Input 0 is incompatible with layer min_max_pooling1d_5: expected ndim=3, found ndim=2
Upvotes: 2
Views: 3905
Reputation: 3485
So what you want to build is a Keras Layer that will take 3D input of shape [batch_dim, pool_dim, channels]
and produce 4D output [batch_dim, pool_dim, channels, min_max_channels]
.
Unlike Keras _Pooling1D
you will actually change the number of dimensions, and I would recommend to implement your layer by inheriting directly from keras Layer
.
Implement the call
method using tf.sort
and taking the desired amount of max and min elements from the sorted input, and concatenating them along a new dimension (consider using tf.expand_dims
and tf.concat
).
p.s. I have tried to implement this myself, and have discovered it to be complicated. You basicly want something different from maxpool, and slightly more. You might take a look at tensorflow/python/ops/gen_nn_ops.py
method max_pool
to appreciate what kind of work you are in for, unless you can find some ready implementation somewhere...
Upvotes: 5
Reputation: 835
Instead of trying to use a Pooling Layer, I am using a Lambda:
def top_k(inputs, k):
return tf.nn.top_k(inputs, k=k, sorted=True).values
def least_k(inputs, k):
return -tf.nn.top_k(-inputs, k=k, sorted = True).values
def minmax_k(inputs, k):
return tf.concat([least_k(inputs, k), top_k(inputs, k)], axis = -1)
model = Sequential()
...
model.add(Lambda(minmax_k, arguments={'k': R}))
Upvotes: 5