xiaoxiaokeke 2020-01-03
函数形式比较简单的时候可以用lambda
函数:
clipped_relu = lambda x: K.activations.relu(x, max_value=4000)
class MLPBlock(Layer): def __init__(self): super(MLPBlock, self).__init__() self.dense_1 = K.layers.Dense(500, kernel_regularizer=regularizers.l2(0.0)) self.dense_2 = K.layers.Dense(500, kernel_regularizer=regularizers.l2(0.0)) self.dense_3 = K.layers.Dense(500, kernel_regularizer=regularizers.l2(0.0)) self.dense_4 = K.layers.Dense(500, kernel_regularizer=regularizers.l2(0.0)) self.dense_5 = K.layers.Dense(60) def call(self, inputs): x = self.dense_1(inputs) x = tf.nn.relu(x) x = self.dense_2(x) x = tf.nn.relu(x) x = self.dense_3(x) x = tf.nn.relu(x) x = self.dense_4(x) x = tf.nn.relu(x) x = self.dense_5(x) return clipped_relu(x)
这一步比较关键, 之前不成功主要是因为没有理解def call(self, inputs)
这个类方法. 以下代码会报错:
input_layer = K.Input(shape=(8,)) output_layer = MLPBlock() mdl = K.Model(input_layer, output_layer) mdl.summary()
这是因为output_layer
未被初始化, 不含input_shape
这个重要信息, 只有当我们把input_layer
作为参数传入自定义的output_layer
时, output_layer
才会被实际地初始化. 因此
input_layer = K.Input(shape=(8,)) output_layer = MLPBlock()(input_layer) mdl = K.Model(input_layer, output_layer) mdl.summary()
可以看到, 我们自定义的由多层Dense Layer叠加(stack)起来的新的Layer, 在形式上被作为一个新的Layer.
Model: "model_5" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_8 (InputLayer) [(None, 8)] 0 _________________________________________________________________ mlp_block_17 (MLPBlock) (None, 60) 786060 ================================================================= Total params: 786,060 Trainable params: 786,060 Non-trainable params: 0 _________________________________________________________________
这里有一个重要的bug, 或者说keras
和tf.keras
不同的地方. 以上代码适用于tf.keras
, 如果使用的是keras
, mlp_block_17 (MLPBlock)
的Output Shape
是(None, 8)
, 而不是(None, 60)
. 有人在github上发现了相同的问题:https://github.com/tensorflow/tensorflow/issues/33785
二者的API可能略有不同, 如果查看Keras官方主页的说明:https://keras.io/layers/writing-your-own-keras-layers/, 在自定义Layer时, 还需要定义一个def compute_output_shape
, 在tf.keras中没有这一步, 官方教程(https://www.tensorflow.org/guide/keras/custom_layers_and_models)里也没有这一步. 换言之, 如果使用tf.keras
, output_shape能够自动得到. 因此如果使用的是keras
而不是tf.keras
, 记得定义def compute_output_shape