TensorFlow2.0教程-用keras構建本身的網絡層

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的方法構建權重python

 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構建網絡session

 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

能夠經過構建網絡層的方法來收集lossdom

 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.其餘網絡層配置

使本身的網絡層能夠序列化ui

 

 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類來定義外部模型 - 即要訓練的對象。lua

Model類與Layer的區別:spa

它公開了內置的訓練,評估和預測循環(model.fit(),model.evaluate(),model.predict())。
它經過model.layers屬性公開其內層列表。
它公開了保存和序列化API。
下面經過構建一個變分自編碼器(VAE),來介紹如何構建本身的網絡。code

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         
相關文章
相關標籤/搜索