2

Я пытаюсь воссоздать CNN уровня char в this paper и немного застрял на последнем этапе, где мне нужно создать слой пула k-max, потому что я использую MXNet, и это не имеет этого.Python KMax Pooling (MXNet)

Важным отличием является также введение нескольких временных слоев k-max. Это позволяет обнаруживать k наиболее важных функций в предложении, независимо от их конкретной позиции, , сохраняя их относительный порядок.

Однако MXNet имеет способность к add a new-op, который я пытался сделать вот так (хотя получаю немного путают с формой данных, данные фильтры и периодического размера).

Форма данных, поступающих в систему:

128 (min-batch) x 512 (number of filters) x 1 (height) x 125 (width) 

Форма данных выходит (к-тах пулы, к = 7):

128 (min-batch) x 512 (number of filters) x 1 (height) x 7 (width) 

Моя идея до сих пор .. .:

class KMaxPooling(mx.operator.CustomOp): 
    def forward(self, is_train, req, in_data, out_data, aux): 
     # Desired (k=3): 
     # in_data = np.array([1, 2, 4, 10, 5, 3]) 
     # out_data = [4, 10, 5] 
     x = in_data[0].asnumpy() 
     idx = x.argsort()[-k:] 
     idx.sort(axis=0) 
     y = x[idx] 

Однако, я не уверен, о нескольких вещах:

  1. Как проверить, работает ли это (если у меня есть полный код)
  2. Какими должны быть размеры? Я сортирую по последнему размеру (ось = 0)
  3. Что делать для функции обратного(), то есть градиентной пропуски
  4. Будет ли это работать с GPU - я предполагаю, что мне придется переписать его в C/CUDA?

Я нашел этот пример кого-то еще для keras (но не имеют респ ссылке):

import numpy as np 
import theano.tensor as T 
from keras.layers.core import MaskedLayer 

class KMaxPooling(MaskedLayer): 
    def __init__(self, pooling_size): 
     super(MaskedLayer, self).__init__() 
     self.pooling_size = pooling_size 
     self.input = T.tensor3() 

    def get_output_mask(self, train=False): 
     return None 

    def get_output(self, train=False): 
     data = self.get_input(train) 
     mask = self.get_input_mask(train) 

     if mask is None: 
      mask = T.sum(T.ones_like(data), axis=-1) 
     mask = mask.dimshuffle(0, 1, "x") 

     masked_data = T.switch(T.eq(mask, 0), -np.inf, data) 

     result = masked_data[T.arange(masked_data.shape[0]).dimshuffle(0, "x", "x"), 
          T.sort(T.argsort(masked_data, axis=1)[:, -self.pooling_size:, :], axis=1), 
          T.arange(masked_data.shape[2]).dimshuffle("x", "x", 0)] 

ответ

1

В самом деле, нет никакой поддержки KMaxPooling в Mxnet до сих пор, и это может быть сложно реализовать его. Тем не менее, я могу думать о некоторых советов, которые помогут вам, если вы решите его реализации:

  1. Если вы используете ГЛЮОНА, то вы можете реализовать KMaxPooling как HybridBlock, а затем использовать HybridSequential, чтобы запустить его. Пока вы используете функции из предоставленного в качестве аргумента «F» -backend (избегайте использования numpy), вы сможете запустить свой код на графическом процессоре. Таким образом, вам не нужно делать C++.

  2. Использование HybridBlock и функций из «F» -backend также также решит проблему обратного распространения. Вам в основном не нужно писать, потому что Autograd сделает это за вас.

  3. С HybridBlock вы можете легче отлаживать код. Вы просто не вызываете метод net.hybridize(), и получаете «nd» -backend, который медленнее, чем «sym» -backend, но позволяет использовать отладчик.

  4. Что касается размеров, если вы заметили, что в Gluon есть версия версии MaxPool: MaxPool1D, MaxPool2D, MaxPool3D. Вы можете реализовать только 1 KMaxPool1D для вашего случая.Затем вы будете складывать вывод KMaxPool1D, как если бы было применено несколько фильтров, по существу добавляя значения в конец «z» -размера.

Надеюсь, что это поможет.