Keras Layer 的 call(x) 和 input_shape

今天用Keras編程的時候發現一個問題,

···
input_layer = K.layers.Input(shape=(10,))

x = K.layers.Dense(20)(input_layer)
x = K.layers.Dense(20)(x)
···
以上寫法是可行的,但是以下寫法卻不行

L = K.layers.Dense(20)
y = L(input_layer)
y = L(y)

前兩個表達式正常,到了第3個表達式y=L(y)的時候就報input_shape錯誤。百思不得其解,按照Python編程的原則,一切皆對象

L = K.layers.Dense(20)
L(x)

K.layers.Dense(20)(x)

有何不同?

一番嘗試,發現奧妙在於Keras Layers的設計。看一下官方的對於自定義Layer的說明,

call(x): this is where the layer's logic lives. Unless you want your layer to support masking, you only have to care about the first argument passed to call: the input tensor.

也就是說,當layer的callmethod被調用時,layer才實際存在,此時將傳入input_shape。如果call沒有被調用,此時layer中並沒有input_shape的信息。

舉例說明,

L = K.layers.Dense(20)
L.input_shape

此時編譯器報錯`AttributeError: The layer has never been called and thus has no defined input shape. 再看以下代碼,

L = K.layers.Dense(20)
y = L(input_layer)
L.input_shape

此時編譯器不報錯,輸出(None, 10)。照理說第二段代碼並沒有對L做任何操作,只是將L(input_layer)賦給了y,但是此時L確獲得了input_shape這個參數。

結合call(x)的定義,一開始遇到的問題也就明白了。表達式y = L(input_layer)調用了Lcallmethod,此時L這個layer才正式被初始化,其input_shape也根據傳入的input_layer被賦值 。因此,此時的L其實已經跟表達式K.layers.Dense(20)不一樣了,後者未被調用,input_shape不存在。

以下這段代碼之所以報input_shape錯誤,就是因爲y = L(input_layer)使得L的input_shape被初始化爲(10,)。因次當第三個表達式y=L(y)y被傳入L時,由於y的shape並不是(10,),而是(20,),與L中input_shape的值不一致,編譯器報錯。

L = K.layers.Dense(20)
y = L(input_layer)
y = L(y)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章