keras中的mask操作
使用背景
最常見的一種情況, 在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
情況.
使用方法
最直接的, 在
NLP
問題中, 對句子填補之後, 就要輸入到Embedding
層中, 將token
由id
轉換成對應的vector
. 我們希望被填補的0值在後續的計算中不產生影響, 就可以在初始化Embedding
層時指定參數mask_zero
為True
, 意思就是屏蔽0值, 即填補的0值.在
Embedding
層中的compute_mask
方法中, 會計算得到mask
矩陣. 雖然在Embedding
層中不會使用這個mask
mask
矩陣會被傳入到下一層中, 如果下一層, 或之後的層會對mask
進行考慮, 那就會起到對應的作用.也可以在
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操作