用keras构建自己的网络层

tensorflow 2.0 学习记录

用keras构建自己的网络层

1.构建一个简单的网络层
from __future__ import absolute_import, division, print_function
import tensorflow as tf
tf.keras.backend.clear_session()
import tensorflow.keras as keras
import tensorflow.keras.layers as layers

class MyLayer(layers.Layer):
    def __init__(self, input_dim=32, unit=32):
        super(MyLayer, self).__init__()
        #自定义权重
        w_init = tf.random_normal_initializer()
        self.weight = tf.Variable(initial_value=w_init(
            shape=(input_dim, unit), dtype=tf.float32), trainable=True)
        
        b_init = tf.zeros_initializer()
        self.bias = tf.Variable(initial_value=b_init(
            shape=(unit,), dtype=tf.float32), trainable=True)
    
    def call(self, inputs):
        return tf.matmul(inputs, self.weight) + self.bias
        
x = tf.ones((3,5))
my_layer = MyLayer(5, 4)
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[0.06709253 0.06818779 0.09926171 0.0179923 ]
 [0.06709253 0.06818779 0.09926171 0.0179923 ]
 [0.06709253 0.06818779 0.09926171 0.0179923 ]], shape=(3, 4), dtype=float32)
 '''
按上面构建网络层,图层会自动跟踪权重w和b,当然我们也可以直接用add_weight的方法构建权重
#使用add_weight方法添加权重
class MyLayer(layers.Layer):
    def __init__(self, input_dim=32, unit=32):
        super(MyLayer, self).__init__()
        self.weight = self.add_weight(shape=(input_dim, unit),
                                     initializer=keras.initializers.RandomNormal(),
                                     trainable=True)
        self.bias = self.add_weight(shape=(unit,),
                                   initializer=keras.initializers.Zeros(),
                                   trainable=True)
    
    def call(self, inputs):
        return tf.matmul(inputs, self.weight) + self.bias
        
x = tf.ones((3,5))
my_layer = MyLayer(5, 4)
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[-0.10401802 -0.05459599 -0.08195674  0.13151655]
 [-0.10401802 -0.05459599 -0.08195674  0.13151655]
 [-0.10401802 -0.05459599 -0.08195674  0.13151655]], shape=(3, 4), dtype=float32)
'''
**当定义网络时不知道网络的维度是可以重写build()函数,用获得的shape构建网络**
class MyLayer(layers.Layer):
    def __init__(self, unit=32):
        super(MyLayer, self).__init__()
        self.unit = unit
        
    def build(self, input_shape):
        self.weight = self.add_weight(shape=(input_shape[-1], self.unit),
                                     initializer=keras.initializers.RandomNormal(),
                                     trainable=True)
        self.bias = self.add_weight(shape=(self.unit,),
                                   initializer=keras.initializers.Zeros(),
                                   trainable=True)
    **#build函数根据inputs的维度确定weight的维度**
    def call(self, inputs):
        return tf.matmul(inputs, self.weight) + self.bias
my_layer = MyLayer(3)
x = tf.ones((3,5))
out = my_layer(x)
print(out)
my_layer = MyLayer(3)
x = tf.ones((2,2))
out = my_layer(x)
print(out)
'''
结果
tf.Tensor(
[[ 0.00949192 -0.02009935 -0.11726624]
 [ 0.00949192 -0.02009935 -0.11726624]
 [ 0.00949192 -0.02009935 -0.11726624]], shape=(3, 3), dtype=float32)
tf.Tensor(
[[-0.00516411 -0.04891593 -0.0181773 ]
 [-0.00516411 -0.04891593 -0.0181773 ]], shape=(2, 3), dtype=float32)
'''
2.使用子层递归构建网络层
class MyBlock(layers.Layer):
    def __init__(self):
        super(MyBlock, self).__init__()
        self.layer1 = MyLayer(32)
        self.layer2 = MyLayer(16)
        self.layer3 = MyLayer(2)
    def call(self, inputs):
        h1 = self.layer1(inputs)
        h1 = tf.nn.relu(h1)
        h2 = self.layer2(h1)
        h2 = tf.nn.relu(h2)
        return self.layer3(h2)
my_block = MyBlock()
print('trainable weights:', len(my_block.trainable_weights))
y = my_block(tf.ones(shape=(3, 64)))
# 构建网络在build()里面,所以执行了才有网络
print('trainable weights:', len(my_block.trainable_weights))
'''
结果
trainable weights: 0
trainable weights: 6
'''
可以通过构建网络层的方法来收集loss
class LossLayer(layers.Layer):
  
  def __init__(self, rate=1e-2):
    super(LossLayer, self).__init__()
    self.rate = rate
  
  def call(self, inputs):
    self.add_loss(self.rate * tf.reduce_sum(inputs))
    return inputs

class OutLayer(layers.Layer):
    def __init__(self):
        super(OutLayer, self).__init__()
        self.loss_fun=LossLayer(1e-2)
    def call(self, inputs):
        return self.loss_fun(inputs)
    
my_layer = OutLayer()
print(len(my_layer.losses)) # 还未call
y = my_layer(tf.zeros(1,1))
print(len(my_layer.losses)) # 执行call之后
y = my_layer(tf.zeros(1,1))
print(len(my_layer.losses)) # call之前会重新置0
'''
结果
0
1
1
'''
3.其他网络层配置
使自己的网络层可以序列化
class Linear(layers.Layer):

    def __init__(self, units=32, **kwargs):
        super(Linear, self).__init__(**kwargs)
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(shape=(input_shape[-1], self.units),
                                 initializer='random_normal',
                                 trainable=True)
        self.b = self.add_weight(shape=(self.units,),
                                 initializer='random_normal',
                                 trainable=True)
    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b
    
    def get_config(self):
        config = super(Linear, self).get_config()
        config.update({'units':self.units})
        return config
layer = Linear(125)
config = layer.get_config()
print(config)
'''
结果
{'name': 'linear_1', 'trainable': True, 'dtype': None, 'units': 125}
'''

发布了12 篇原创文章 · 获赞 1 · 访问量 190

猜你喜欢

转载自blog.csdn.net/weixin_42813521/article/details/105522972
今日推荐