自定义 Layer
自定义激活函数
函数形式比较简单的时候可以用lambda
函数:
clipped_relu = lambda x: K.activations.relu(x, max_value=4000)
Layer类
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
_________________________________________________________________
以上自定义Layer的方法适用于tf.keras
, 但不适用于Keras
, 两者的API在自定义Layer方面有所不同. 根据我对官方说明的理解, tf.keras
可以像前面的代码那样, 把许多现有的Layer叠加在一起, 形成一个新的自定义Layer, 而Keras
中自定义Layer的时候似乎不能用这种方式来自定义Layer, 但可以用自定义Model的形式来实现, 如下面这段官方教程的代码
import keras
class SimpleMLP(keras.Model):
def __init__(self, use_bn=False, use_dp=False, num_classes=10):
super(SimpleMLP, self).__init__(name='mlp')
self.use_bn = use_bn
self.use_dp = use_dp
self.num_classes = num_classes
self.dense1 = keras.layers.Dense(32, activation='relu')
self.dense2 = keras.layers.Dense(num_classes, activation='softmax')
if self.use_dp:
self.dp = keras.layers.Dropout(0.5)
if self.use_bn:
self.bn = keras.layers.BatchNormalization(axis=-1)
def call(self, inputs):
x = self.dense1(inputs)
if self.use_dp:
x = self.dp(x)
if self.use_bn:
x = self.bn(x)
return self.dense2(x)
model = SimpleMLP()
model.compile(...)
model.fit(...)