0

Has the Weldon pooling [1] been implemented in Keras?

I can see that it has been implemented in pytorch by the authors [2] but cannot find a keras equivalent.

[1] T. Durand, N. Thome, and M. Cord. Weldon: Weakly su- pervised learning of deep convolutional neural networks. In CVPR, 2016. [2] https://github.com/durandtibo/weldon.resnet.pytorch/tree/master/weldon

biogeek
  • 561
  • 1
  • 4
  • 13

1 Answers1

1

Here is one based on the lua version (there is a pytorch impl but i think that has an error taking the average of max+min). I'm assuming the lua version's avg of top max and min values was still correct. I've not tested the whole custom layer aspects but close enough to get something going, comments welcomed.

Tony

class WeldonPooling(Layer):
    """Class to implement Weldon selective spacial pooling with negative evidence
    """

    #@interfaces.legacy_global_pooling_support
    def __init__(self, kmax, kmin=-1, data_format=None, **kwargs):
        super(WeldonPooling, self).__init__(**kwargs)
        self.data_format = conv_utils.normalize_data_format(data_format)
        self.input_spec = InputSpec(ndim=4)
        self.kmax=kmax
        self.kmin=kmin

    def compute_output_shape(self, input_shape):
        if self.data_format == 'channels_last':
            return (input_shape[0], input_shape[3])
        else:
            return (input_shape[0], input_shape[1])

    def get_config(self):
        config = {'data_format': self.data_format}
        base_config = super(_GlobalPooling2D, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

    def call(self, inputs):
        if self.data_format == "channels_last":
            inputs = tf.transpose(inputs, [0, 3, 1, 2])
        kmax=self.kmax
        kmin=self.kmin
        shape=tf.shape(inputs)
        batch_size = shape[0]
        num_channels = shape[1]
        h = shape[2]
        w = shape[3]
        n = h * w
        view = tf.reshape(inputs, [batch_size, num_channels, n])
        sorted, indices = tf.nn.top_k(view, n, sorted=True)
        #indices_max = tf.slice(indices,[0,0,0],[batch_size, num_channels, kmax])
        output = tf.div(tf.reduce_sum(tf.slice(sorted,[0,0,0],[batch_size, num_channels, kmax]),2),kmax)

        if kmin > 0:
            #indices_min = tf.slice(indices,[0,0, n-kmin],[batch_size, num_channels, kmin])
            output=tf.add(output,tf.div(tf.reduce_sum(tf.slice(sorted,[0,0,n-kmin],[batch_size, num_channels, kmin]),2),kmin))

        return tf.reshape(output,[batch_size, num_channels])
Ioannis Nasios
  • 8,292
  • 4
  • 33
  • 55
Tony
  • 46
  • 1
  • also note this was only for use with TF backend. the "tf." could be replace with "K.tf." to make it more Keras-y. For the other backends it would need their specific implementations because there were no abstraction of the required operations. – Tony Apr 24 '18 at 12:13