1. 程式人生 > >keras中的mask操作

keras中的mask操作

init 原理 進行變換 blog details ret pool 位置 art

使用背景

最常見的一種情況, 在NLP問題的句子補全方法中, 按照一定的長度, 對句子進行填補和截取操作. 一般使用keras.preprocessing.sequence包中的pad_sequences方法, 在句子前面或者後面補0. 但是這些零是我們不需要的, 只是為了組成可以計算的結構才填補的. 因此計算過程中, 我們希望用mask的思想, 在計算中, 屏蔽這些填補0值得作用. keras中提供了mask相關的操作方法.

原理

在keras中, Tensor在各層之間傳遞, Layer對象接受的上層Layer得到的Tensor, 輸出的經過處理後的Tensor.

keras是用一個mask矩陣來參與到計算當中, 決定在計算中屏蔽哪些位置的值. 因此mask

矩陣其中的值就是True/False, 其形狀一般與對應的Tensor相同. 同樣與Tensor相同的是, mask矩陣也會在每層Layer被處理, 得到傳入到下一層的mask情況.

使用方法

  1. 最直接的, 在NLP問題中, 對句子填補之後, 就要輸入到Embedding層中, 將tokenid轉換成對應的vector. 我們希望被填補的0值在後續的計算中不產生影響, 就可以在初始化Embedding層時指定參數mask_zeroTrue, 意思就是屏蔽0值, 即填補的0值.

    Embedding層中的compute_mask方法中, 會計算得到mask矩陣. 雖然在Embedding層中不會使用這個mask

    矩陣, 即0值還是會根據其對應的向量進行查找, 但是這個mask矩陣會被傳入到下一層中, 如果下一層, 或之後的層會對mask進行考慮, 那就會起到對應的作用.

  2. 也可以在keras.layers包中引用Masking類, 使用mask_value指定固定的值被屏蔽. 在調用call方法時, 就會輸出屏蔽後的結果.

    需要註意的是Masking這種層的compute_mask方法, 源碼如下:

    def compute_mask(self, inputs, mask=None):
        output_mask = K.any(K.not_equal(inputs, self.mask_value), axis=-1)
        return output_mask

    可以看到, 這一層輸出的mask矩陣, 是根據這層的輸入得到的, 具體的說是會比輸入第一個維度, 這是因為最後一個維度被K.any(axis=-1)給去掉了. 在使用時需要註意這種操作的意義以及維度的變化.

自定義使用方法

更多的, 我們還是在自定義的層中, 需要支持mask操作, 因此需要對應的邏輯.


首先, 如果我們希望自定義的這個層支持mask操作, 就需要在__init__方法中指定:

self.supports_masking = True

如果在本層計算中需要使用到mask, 則call方法需要多傳入一個mask參數, 即:

def call(self, inputs, mask=None):
    pass

然後, 如果還要繼續輸出mask, 供之後的層使用, 如果不對mask矩陣進行變換, 這不用進行任何操作, 否則就需要實現compute_mask函數:

def compute_mask(self, inputs, mask=None):
    pass

這裏的inputs就是輸入的Tensor, 與call方法中接收到的一樣, mask就是上層傳入的mask矩陣.

如果希望mask到此為止, 之後的層不再使用, 則該函數直接返回None即可:

def compute_mask(self, inputs, mask=None):
    return None

參考資料

Keras自定義實現帶masking的meanpooling層

Keras實現支持masking的Flatten層

keras中的mask操作