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的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)