用keras构建自己的网络层 TensorFlow2.0教程
1.构建一个简单的网络层
1 from __future__ import absolute_import, division, print_function 2 import tensorflow as tf 3 tf.keras.backend.clear_session() 4 import tensorflow.keras as keras 5 import tensorflow.keras.layers as layers
1 # 定义网络层就是:设置网络权重和输出到输入的计算过程 2 class MyLayer(layers.Layer): 3 def __init__(self, input_dim=32, unit=32): 4 super(MyLayer, self).__init__() 5 6 w_init = tf.random_normal_initializer() 7 self.weight = tf.Variable(initial_value=w_init( 8 shape=(input_dim, unit), dtype=tf.float32), trainable=True) 9 10 b_init = tf.zeros_initializer() 11 self.bias = tf.Variable(initial_value=b_init( 12 shape=(unit,), dtype=tf.float32), trainable=True) 13 14 def call(self, inputs): 15 return tf.matmul(inputs, self.weight) + self.bias 16 17 x = tf.ones((3,5)) 18 my_layer = MyLayer(5, 4) 19 out = my_layer(x) 20 print(out) 21 22
1 tf.Tensor( 2 [[0.06709253 0.06818779 0.09926171 0.0179923 ] 3 [0.06709253 0.06818779 0.09926171 0.0179923 ] 4 [0.06709253 0.06818779 0.09926171 0.0179923 ]], shape=(3, 4), dtype=float32)
按上面构建网络层,图层会自动跟踪权重w和b,当然我们也可以直接用add_weight的方法构建权重
1 class MyLayer(layers.Layer): 2 def __init__(self, input_dim=32, unit=32): 3 super(MyLayer, self).__init__() 4 self.weight = self.add_weight(shape=(input_dim, unit), 5 initializer=keras.initializers.RandomNormal(), 6 trainable=True) 7 self.bias = self.add_weight(shape=(unit,), 8 initializer=keras.initializers.Zeros(), 9 trainable=True) 10 11 def call(self, inputs): 12 return tf.matmul(inputs, self.weight) + self.bias 13 14 x = tf.ones((3,5)) 15 my_layer = MyLayer(5, 4) 16 out = my_layer(x) 17 print(out) 18
1 tf.Tensor( 2 [[-0.10401802 -0.05459599 -0.08195674 0.13151655] 3 [-0.10401802 -0.05459599 -0.08195674 0.13151655] 4 [-0.10401802 -0.05459599 -0.08195674 0.13151655]], shape=(3, 4), dtype=float32)
也可以设置不可训练的权重
1 class AddLayer(layers.Layer): 2 def __init__(self, input_dim=32): 3 super(AddLayer, self).__init__() 4 self.sum = self.add_weight(shape=(input_dim,), 5 initializer=keras.initializers.Zeros(), 6 trainable=False) 7 8 9 def call(self, inputs): 10 self.sum.assign_add(tf.reduce_sum(inputs, axis=0)) 11 return self.sum 12 13 x = tf.ones((3,3)) 14 my_layer = AddLayer(3) 15 out = my_layer(x) 16 print(out.numpy()) 17 out = my_layer(x) 18 print(out.numpy()) 19 print('weight:', my_layer.weights) 20 print('non-trainable weight:', my_layer.non_trainable_weights) 21 print('trainable weight:', my_layer.trainable_weights)
1 [3. 3. 3.] 2 [6. 6. 6.] 3 weight: [<tf.Variable 'Variable:0' shape=(3,) dtype=float32, numpy=array([6., 6., 6.], dtype=float32)>] 4 non-trainable weight: [<tf.Variable 'Variable:0' shape=(3,) dtype=float32, numpy=array([6., 6., 6.], dtype=float32)>] 5 trainable weight: []
当定义网络时不知道网络的维度是可以重写build()函数,用获得的shape构建网络
1 class MyLayer(layers.Layer): 2 def __init__(self, unit=32): 3 super(MyLayer, self).__init__() 4 self.unit = unit 5 6 def build(self, input_shape): 7 self.weight = self.add_weight(shape=(input_shape[-1], self.unit), 8 initializer=keras.initializers.RandomNormal(), 9 trainable=True) 10 self.bias = self.add_weight(shape=(self.unit,), 11 initializer=keras.initializers.Zeros(), 12 trainable=True) 13 14 def call(self, inputs): 15 return tf.matmul(inputs, self.weight) + self.bias 16 17 18 my_layer = MyLayer(3) 19 x = tf.ones((3,5)) 20 out = my_layer(x) 21 print(out) 22 my_layer = MyLayer(3) 23 24 x = tf.ones((2,2)) 25 out = my_layer(x) 26 print(out)
1 tf.Tensor( 2 [[ 0.00949192 -0.02009935 -0.11726624] 3 [ 0.00949192 -0.02009935 -0.11726624] 4 [ 0.00949192 -0.02009935 -0.11726624]], shape=(3, 3), dtype=float32) 5 tf.Tensor( 6 [[-0.00516411 -0.04891593 -0.0181773 ] 7 [-0.00516411 -0.04891593 -0.0181773 ]], shape=(2, 3), dtype=float32)
2.使用子层递归构建网络层
1 class MyBlock(layers.Layer): 2 def __init__(self): 3 super(MyBlock, self).__init__() 4 self.layer1 = MyLayer(32) 5 self.layer2 = MyLayer(16) 6 self.layer3 = MyLayer(2) 7 def call(self, inputs): 8 h1 = self.layer1(inputs) 9 h1 = tf.nn.relu(h1) 10 h2 = self.layer2(h1) 11 h2 = tf.nn.relu(h2) 12 return self.layer3(h2) 13 14 my_block = MyBlock() 15 print('trainable weights:', len(my_block.trainable_weights)) 16 y = my_block(tf.ones(shape=(3, 64))) 17 # 构建网络在build()里面,所以执行了才有网络 18 print('trainable weights:', len(my_block.trainable_weights))
1 trainable weights: 0 2 trainable weights: 6
可以通过构建网络层的方法来收集loss
1 class LossLayer(layers.Layer): 2 3 def __init__(self, rate=1e-2): 4 super(LossLayer, self).__init__() 5 self.rate = rate 6 7 def call(self, inputs): 8 self.add_loss(self.rate * tf.reduce_sum(inputs)) 9 return inputs 10 11 class OutLayer(layers.Layer): 12 def __init__(self): 13 super(OutLayer, self).__init__() 14 self.loss_fun=LossLayer(1e-2) 15 def call(self, inputs): 16 return self.loss_fun(inputs) 17 18 my_layer = OutLayer() 19 print(len(my_layer.losses)) # 还未call 20 y = my_layer(tf.zeros(1,1)) 21 print(len(my_layer.losses)) # 执行call之后 22 y = my_layer(tf.zeros(1,1)) 23 print(len(my_layer.losses)) # call之前会重新置0
1 0 2 1 3 1
如果中间调用了keras网络层,里面的正则化loss也会被加入进来
1 class OuterLayer(layers.Layer): 2 3 def __init__(self): 4 super(OuterLayer, self).__init__() 5 self.dense = layers.Dense(32, kernel_regularizer=tf.keras.regularizers.l2(1e-3)) 6 7 def call(self, inputs): 8 return self.dense(inputs) 9 10 11 my_layer = OuterLayer() 12 y = my_layer(tf.zeros((1,1))) 13 print(my_layer.losses) 14 print(my_layer.weights)
1 [<tf.Tensor: id=413, shape=(), dtype=float32, numpy=0.0018067828>] 2 [<tf.Variable 'outer_layer_1/dense_1/kernel:0' shape=(1, 32) dtype=float32, numpy= 3 array([[-0.11054656, 0.34735924, -0.22560999, 0.38415992, 0.13070339, 4 0.15960163, 0.20130599, 0.40365922, -0.09471637, -0.02402192, 5 0.16438413, 0.2716753 , 0.0594548 , -0.06913272, -0.40491152, 6 0.00894281, 0.3199494 , 0.0228827 , -0.18515846, 0.32210535, 7 0.41672045, 0.1942389 , -0.4254937 , 0.07178113, 0.00740242, 8 0.23780417, -0.24449413, -0.15526545, -0.2200018 , -0.2426699 , 9 -0.17750363, -0.16994882]], dtype=float32)>, <tf.Variable 'outer_layer_1/dense_1/bias:0' shape=(32,) dtype=float32, numpy= 10 array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 12 dtype=float32)>]
3.其他网络层配置
使自己的网络层可以序列化
1 class Linear(layers.Layer): 2 3 def __init__(self, units=32, **kwargs): 4 super(Linear, self).__init__(**kwargs) 5 self.units = units 6 7 def build(self, input_shape): 8 self.w = self.add_weight(shape=(input_shape[-1], self.units), 9 initializer='random_normal', 10 trainable=True) 11 self.b = self.add_weight(shape=(self.units,), 12 initializer='random_normal', 13 trainable=True) 14 def call(self, inputs): 15 return tf.matmul(inputs, self.w) + self.b 16 17 def get_config(self): 18 config = super(Linear, self).get_config() 19 config.update({'units':self.units}) 20 return config 21 22 23 layer = Linear(125) 24 config = layer.get_config() 25 print(config) 26 new_layer = Linear.from_config(config)
1 {'name': 'linear_1', 'trainable': True, 'dtype': None, 'units': 125}
配置只有训练时可以执行的网络层
1 class MyDropout(layers.Layer): 2 def __init__(self, rate, **kwargs): 3 super(MyDropout, self).__init__(**kwargs) 4 self.rate = rate 5 def call(self, inputs, training=None): 6 return tf.cond(training, 7 lambda: tf.nn.dropout(inputs, rate=self.rate), 8 lambda: inputs) 9 10
4.构建自己的模型
通常,我们使用Layer类来定义内部计算块,并使用Model类来定义外部模型 - 即要训练的对象。
Model类与Layer的区别:
它公开了内置的训练,评估和预测循环(model.fit(),model.evaluate(),model.predict())。
它通过model.layers属性公开其内层列表。
它公开了保存和序列化API。
下面通过构建一个变分自编码器(VAE),来介绍如何构建自己的网络。
class MyDropout(layers.Layer): def __init__(self, rate, **kwargs): super(MyDropout, self).__init__(**kwargs) self.rate = rate def call(self, inputs, training=None): return tf.cond(training, lambda: tf.nn.dropout(inputs, rate=self.rate), lambda: inputs)
1 class MyDropout(layers.Layer): 2 def __init__(self, rate, **kwargs): 3 super(MyDropout, self).__init__(**kwargs) 4 self.rate = rate 5 def call(self, inputs, training=None): 6 return tf.cond(training, 7 lambda: tf.nn.dropout(inputs, rate=self.rate), 8 lambda: inputs) 9 10
1 class MyDropout(layers.Layer): 2 def __init__(self, rate, **kwargs): 3 super(MyDropout, self).__init__(**kwargs) 4 self.rate = rate 5 def call(self, inputs, training=None): 6 return tf.cond(training, 7 lambda: tf.nn.dropout(inputs, rate=self.rate), 8 lambda: inputs) 9 10
自己编写训练方法
1 class MyDropout(layers.Layer): 2 def __init__(self, rate, **kwargs): 3 super(MyDropout, self).__init__(**kwargs) 4 self.rate = rate 5 def call(self, inputs, training=None): 6 return tf.cond(training, 7 lambda: tf.nn.dropout(inputs, rate=self.rate), 8 lambda: inputs) 9 10
1 class MyDropout(layers.Layer): 2 def __init__(self, rate, **kwargs): 3 super(MyDropout, self).__init__(**kwargs) 4 self.rate = rate 5 def call(self, inputs, training=None): 6 return tf.cond(training, 7 lambda: tf.nn.dropout(inputs, rate=self.rate), 8 lambda: inputs) 9 10 如果还有问题未能得到解决,搜索887934385交流群,进入后下载资料工具安装包等。最后,感谢观看!