• 用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交流群,进入后下载资料工具安装包等。最后,感谢观看!     
  • 相关阅读:
    Codeforces 960B(优先队列)
    “景驰科技杯”2018年华南理工大学程序设计竞赛 H-对称与反对称(逆元)
    AcWing
    POJ
    POJ
    AtCoder
    HRBUST
    CodeForces
    HYSBZ
    HDU
  • 原文地址:https://www.cnblogs.com/pypypy/p/11935384.html
Copyright © 2020-2023  润新知