2

我想重新創建this paper中的字符級CNN,並且在最後一步需要創建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) 

數據中出來的形狀(K-MAX池中,k = 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. 尺寸應該是什麼?我正在對最後一個維度進行排序(axis = 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

的確,在Mxnet沒有KMaxPooling支持,到目前爲止,它可能是很難實施它。然而,我能想到的一些技巧來幫助你,如果你決定實現它:

  1. 如果您使用的膠子,那麼你就可以實現KMaxPooling作爲HybridBlock然後用HybridSequential運行它。只要你使用提供的函數作爲參數「F」-backend(避免使用numpy),你就可以在GPU上運行你的代碼。所以,你不需要做C++。

  2. 僅使用HybridBlock和來自「F」的功能 - 後端也只能解決後向傳播的問題。你基本上不需要寫它,因爲Autograd會爲你做。

  3. 使用HybridBlock,您可以更輕鬆地調試代碼。你只是不要調用net.hybridize()方法,你會得到「nd」-backend,它比「sym」-backend慢,但允許你使用調試器。

  4. 至於尺寸,如果您發現Gluon中存在MaxPool塊的不同版本:MaxPool1D,MaxPool2D,MaxPool3D。您可以只爲您的案例實施1個KMaxPool1D。然後您將堆疊KMaxPool1D的輸出,就好像應用了多個過濾器一樣,實質上將值添加到「z」維的末尾。

希望有所幫助。