2
votes

Qu'est-ce que K Max Pooling? Comment l'implémenter dans Keras?

Je dois ajouter une couche de pooling k-max dans le modèle CNN pour détecter les faux avis. Pouvez-vous me dire comment l'implémenter à l'aide de keras.

J'ai cherché sur Internet mais je n'ai pas de bonnes ressources.


0 commentaires

4 Réponses :


4
votes

Selon cet article , k-Max Pooling est une opération de regroupement qui est une généralisation du pooling max sur la dimension temporelle utilisée dans le modèle de phrase Max-TDNN et différentes des opérations de pooling local max appliquées dans un réseau convolutif pour la reconnaissance d'objets (LeCun et al., 1998).

 entrez la description de l'image ici

L'opération de pooling k-max permet pour regrouper les k caractéristiques les plus actives de p qui peuvent être un certain nombre de positions à part; il préserve l'ordre des fonctionnalités, mais est insensible à leur spécificité positions.

Il existe peu de ressources qui montrent comment l'implémenter dans tensorflow ou keras:


0 commentaires

1
votes

Implémentation Keras de K-Max Pooling avec le backend TensorFlow

Il semble y avoir une solution ici comme @Anubhav_Singh l'a suggéré. Cette réponse a obtenu presque 5 fois plus de pouces vers le haut (24) que de pouces vers le bas (5) sur le lien des problèmes de github keras. Je le cite simplement tel quel ici et je laisse les gens l'essayer et dire si cela a fonctionné pour eux ou non.

Auteur original: arbackus

from keras.engine import Layer, InputSpec
from keras.layers import Flatten
import tensorflow as tf

class KMaxPooling(Layer):
    """
    K-max pooling layer that extracts the k-highest activations from a sequence (2nd dimension).
    TensorFlow backend.
    """
    def __init__(self, k=1, **kwargs):
        super().__init__(**kwargs)
        self.input_spec = InputSpec(ndim=3)
        self.k = k

    def compute_output_shape(self, input_shape):
        return (input_shape[0], (input_shape[2] * self.k))

    def call(self, inputs):

        # swap last two dimensions since top_k will be applied along the last dimension
        shifted_input = tf.transpose(inputs, [0, 2, 1])

        # extract top_k, returns two tensors [values, indices]
        top_k = tf.nn.top_k(shifted_input, k=self.k, sorted=True, name=None)[0]

        # return flattened output
        return Flatten()(top_k)

Remarque: il a été signalé qu'il fonctionnait très lentement (même si cela fonctionnait pour les gens).


0 commentaires

0
votes

Voici une implémentation de la version Pytorch de k-max pooling:

import torch
def kmax_pooling(x, dim, k):
    index = x.topk(k, dim = dim)[1].sort(dim = dim)[0]
    return x.gather(dim, index)

J'espère que cela vous aidera.


0 commentaires

0
votes

Vérifiez ceci. Pas complètement testé mais fonctionne bien pour moi. Laissez-moi savoir ce que vous pensez. P.S. Dernière version de tensorflow.

tf.nn.top_k ne conserve pas l'ordre d'occurrence des valeurs. Donc, c'est la réflexion sur laquelle il faut travailler

import tensorflow as tf
from tensorflow.keras import layers
class KMaxPooling(layers.Layer):
    """
    K-max pooling layer that extracts the k-highest activations from a sequence (2nd dimension).
    TensorFlow backend.
    """
    def __init__(self, k=1, axis=1, **kwargs):
        super(KMaxPooling, self).__init__(**kwargs)
        self.input_spec = layers.InputSpec(ndim=3)
        self.k = k

        assert axis in [1,2],  'expected dimensions (samples, filters, convolved_values),\
                   cannot fold along samples dimension or axis not in list [1,2]'
        self.axis = axis

        # need to switch the axis with the last elemnet
        # to perform transpose for tok k elements since top_k works in last axis
        self.transpose_perm = [0,1,2] #default
        self.transpose_perm[self.axis] = 2
        self.transpose_perm[2] = self.axis

    def compute_output_shape(self, input_shape):
        input_shape_list = list(input_shape)
        input_shape_list[self.axis] = self.k
        return tuple(input_shape_list)

    def call(self, x):
        # swap sequence dimension to get top k elements along axis=1
        transposed_for_topk = tf.transpose(x, perm=self.transpose_perm)

        # extract top_k, returns two tensors [values, indices]
        top_k_vals, top_k_indices = tf.math.top_k(transposed_for_topk,
                                                  k=self.k, sorted=True,
                                                  name=None)
        # maintain the order of values as in the paper
        # sort indices
        sorted_top_k_ind = tf.sort(top_k_indices)
        flatten_seq = tf.reshape(transposed_for_topk, (-1,))
        shape_seq = tf.shape(transposed_for_topk)
        len_seq = tf.shape(flatten_seq)[0]
        indices_seq = tf.range(len_seq)
        indices_seq = tf.reshape(indices_seq, shape_seq)
        indices_gather = tf.gather(indices_seq, 0, axis=-1)
        indices_sum = tf.expand_dims(indices_gather, axis=-1)
        sorted_top_k_ind += indices_sum
        k_max_out = tf.gather(flatten_seq, sorted_top_k_ind)
        # return back to normal dimension but now sequence dimension has only k elements
        # performing another transpose will get the tensor back to its original shape
        # but will have k as its axis_1 size
        transposed_back = tf.transpose(k_max_out, perm=self.transpose_perm)

        return transposed_back


0 commentaires