我想定义我的自定义池层,而不是像MaxPooling层那样返回最大值,它会输出k个最大值和k个最小值。
我使用Tensorflow作为后端。我需要对输出向量进行排序。
我在想这样做:
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:]))
但后来我得到:
Tensor("min_max_pooling1d_1/sort/Neg_1:0", shape=(?, 1, 1, ?), dtype=float32)
ValueError: zero-dimensional arrays cannot be concatenated
Mind MaxPooling1D图层应用于(Non,1,10)形状输出。
我当时正考虑在MinMaxPooling1D之前添加Flatten图层,但是存在尺寸问题:
ValueError: Input 0 is incompatible with layer min_max_pooling1d_5: expected ndim=3, found ndim=2
所以你想要建立的是Keras Layer,它将采用形状[batch_dim, pool_dim, channels]
的3D输入并产生4D输出[batch_dim, pool_dim, channels, min_max_channels]
。
与Keras _Pooling1D
不同,您实际上会更改维度的数量,我建议您通过直接从keras Layer
继承来实现您的图层。
使用call
实现tf.sort
方法,并从排序的输入中获取所需数量的max和min元素,并沿新维度连接它们(考虑使用tf.expand_dims
和tf.concat
)。
附:我自己试图实现这一点,并发现它很复杂。你基本上想要与maxpool不同的东西,稍微复杂一点。你可以看看tensorflow/python/ops/gen_nn_ops.py
方法max_pool
来欣赏你所从事的工作,除非你能找到一些现成的实现...
我没有尝试使用Pooling Layer,而是使用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}))