今天用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的call
method被調用時,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)
調用了L
的call
method,此時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)