用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交流群,进入后下载资料工具安装包等。最后,感谢观看!     
posted @ 2019-11-26 14:45  pypypypy  阅读(627)  评论(0编辑  收藏  举报