keras中Lambda層的使用

在keras中搭建模型常用的方法有兩種:

(1)一種是較爲簡單的序列模型Sequential(該方法適用於搭建簡單的模型)

(2)一種是使用Keras函數式的API(該方法最爲常用)

無論使用哪種方法在搭建model時都要求使用keras中繼承自Layer的層(例如keras.layers.Conv1D等等),但有時候又需要使用一些keras.layers中沒有的層(例如expand_dim, squeeze或者自己定義的層等)。這時候必須想辦法將其轉換成keras中的Layer,一般有兩種方法,一種是直接定義類class然後繼承Layer,一種是直接使用Lambda函數。這裏主要講使用Lambda函數的方法,該方法比較簡單。

例1:定義一個squeeze層,其中x是上一層的輸出,arguments中的axis參數是傳給keras.backend.squeeze的。

from tensorflow import keras

squeeze = keras.layers.Lambda(keras.backend.squeeze, arguments={'axis': -1})(x)

或者:

squeeze = keras.layers.Lambda(lambda x: keras.backend.squeeze(x, axis=-1))(x)

再或者:

def squeeze_function(x):
    return keras.backend.squeeze(x, axis=-1)

squeeze = keras.layers.Lambda(squeeze_function)(x)

-------------------------------------------------------下面的內容可能會誤導大家,謹慎查看

例2:定義一個DepthwiseConv1D層,在keras中並沒有這個層,keras只有SeparableConv1D和Depthwise2D層。(我不確定是否正確僅供參考)

def DepthwiseConv1D(x):
    expand_dim = keras.backend.expand_dims(x, axis=2)
    depthwiseConv2D = keras.layers.DepthwiseConv2D(kernel_size=[int(expand_dim.shape[1], 1)])(expand_dim)
    squeeze_dim = keras.backend.squeeze(depthwiseConv2D, axis=2)
    return squeeze_dim

depwiseconv = keras.layers.Lambda(DepthwiseConv1D)(x)

這裏需要注意下擴展與壓縮哪個維度。

比如我的目的是將(batch,500,16)通過depwiseconv1d變爲(batch,1,16)。輸入的tensor格式是(batch, 500, 16),在擴充維度axis=2後變成了(batch,500,1,16)你可以理解爲是一個高度爲500、寬度爲1、深度爲16的一個矩陣,我們使用了depthwiseconv2d(kernel_size=[500, 1], stride=[1, 1])後變爲(batch,1,1,16),然後壓縮維度axis=2得到我想要的(batch,1,16)。

看到這有人會說爲什麼不去擴展最後一個維度axis=-1,用同樣的kernel和stride也能得到相同的結果,(batch,500,16)->(batch,500,16,1)->(batch,1,16,1)->(batch,1,16)。嗯...我也試過,確實可以,但是有個問題,訓練網絡的速度會比前一個方法慢接近一倍。我猜應該是第二種方法的channel爲1的原因(可能depthwiseconv對多維做了優化但這裏沒能體現出來)。

還有一個問題,使用自己搭建的depthwiseconv1d方法訓練模型收斂很慢,使用自己的depthwiseconv1d加上普通的conv1d效果沒有官方自帶的SeparableConv1D好,如果有大神,還請賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章