Tensorflow自定义网络结构build和call

在创建自定义网络层类时,需要继承自layers.Layer 基类;创建自定义的网络类,需要继承自 keras.Model 基类,这样产生的自定义类才能够方便的利用Layer/Model 基类提供的参数管理功能,同时也能够与其他的标准网络层类交互使用。

一:实现自定义网络层

实现自己的层的最佳方法是扩展tf.keras.Layer类并实现:

> _init_()函数:参数初始化
> 
> build()函数,可以获得输入张量的形状,权重变量初始化
> 
> call()函数,构建网络结构,进行前向传播

实际上,你不必等到调用build()来创建网络结构,您也可以在_init_()中创建它们。 但是,在build()中创建它们的优点是它可以根据图层将要操作的输入的形状启用后期的网络构建。 另一方面,在__init__中创建变量意味着需要明确指定创建变量所需的形状。

class MyDense(tf.keras.layers.Layer):
    def __init__(self, n_outputs):
        super(MyDense, self).__init__()
        self.n_outputs = n_outputs
    
    def build(self, input_shape):
        self.kernel = self.add_variable('kernel',
                                       shape=[int(input_shape[-1]),
                                             self.n_outputs])
    def call(self, input):
        return tf.matmul(input, self.kernel)
layer = MyDense(10)
print(layer(tf.ones([6, 5])))
print(layer.trainable_variables)

使用的时候

//__init__(256)
mlayer=MyLayer(256)
//call(x)
mlayer(x)

其中input_shape是根据input来的
所以在重构build()的时候,layer的权重生成要与input数据shape来推导生成

二、自定义网络

机器学习模型中有很多是通过叠加不同的结构层组合而成的,如resnet的每个残差块就是“卷积+批标准化+残差连接”的组合。

在tensorflow2中要创建一个包含多个网络层的的结构,一般继承与tf.keras.Model类。

# 残差块
class ResnetBlock(tf.keras.Model):
    def __init__(self, kernel_size, filters):
        super(ResnetBlock, self).__init__(name='resnet_block')
        
        # 每个子层卷积核数
        filter1, filter2, filter3 = filters
        
        # 三个子层,每层1个卷积加一个批正则化
        # 第一个子层, 1*1的卷积
        self.conv1 = tf.keras.layers.Conv2D(filter1, (1,1))
        self.bn1 = tf.keras.layers.BatchNormalization()
        # 第二个子层, 使用特点的kernel_size
        self.conv2 = tf.keras.layers.Conv2D(filter2, kernel_size, padding='same')
        self.bn2 = tf.keras.layers.BatchNormalization()
        # 第三个子层,1*1卷积
        self.conv3 = tf.keras.layers.Conv2D(filter3, (1,1))
        self.bn3 = tf.keras.layers.BatchNormalization()
        
    def call(self, inputs, training=False):
        
        # 堆叠每个子层
        x = self.conv1(inputs)
        x = self.bn1(x, training=training)
        
        x = self.conv2(x)
        x = self.bn2(x, training=training)
        
        x = self.conv3(x)
        x = self.bn3(x, training=training)
        
        # 残差连接
        x += inputs
        outputs = tf.nn.relu(x)
        
        return outputs

resnetBlock = ResnetBlock(2, [6,4,9])
# 数据测试
print(resnetBlock(tf.ones([1,3,9,9])))
# 查看网络中的变量名
print([x.name for x in resnetBlock.trainable_variables])

从这个案例中可以发现call函数类似于torch中的forward函数
tf中的call等价于torch中forward

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用 TensorFlow 自定义网络层的步骤如下: 1. 导入必要的库和模块: ```python import tensorflow as tf from tensorflow.keras.layers import Layer ``` 2. 创建自定义层类并继承 Layer 类: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 ``` 3. 在 `__init__` 方法中定义层需要的参数和变量: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 self.arg1 = arg1 self.arg2 = arg2 self.variable1 = self.add_weight(name='variable1', shape=(1,), initializer='zeros') ``` 4. 在 `build` 方法中定义层的权重: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 self.arg1 = arg1 self.arg2 = arg2 def build(self, input_shape): self.variable1 = self.add_weight(name='variable1', shape=(1,), initializer='zeros') self.variable2 = self.add_weight(name='variable2', shape=(input_shape[-1],), initializer='random_normal', trainable=True) ``` 5. 在 `call` 方法中定义层的前向传播逻辑: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 self.arg1 = arg1 self.arg2 = arg2 def build(self, input_shape): self.variable1 = self.add_weight(name='variable1', shape=(1,), initializer='zeros') self.variable2 = self.add_weight(name='variable2', shape=(input_shape[-1],), initializer='random_normal', trainable=True) def call(self, inputs): output = tf.matmul(inputs, self.variable2) + self.variable1 return output ``` 6. 可选:在 `get_config` 方法中定义序列化和反序列化逻辑: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 self.arg1 = arg1 self.arg2 = arg2 def build(self, input_shape): self.variable1 = self.add_weight(name='variable1', shape=(1,), initializer='zeros') self.variable2 = self.add_weight(name='variable2', shape=(input_shape[-1],), initializer='random_normal', trainable=True) def call(self, inputs): output = tf.matmul(inputs, self.variable2) + self.variable1 return output def get_config(self): config = super(CustomLayer, self).get_config() config.update({'arg1': self.arg1, 'arg2': self.arg2}) return config ``` 7. 可选:在 `from_config` 方法中定义从配置中创建层的逻辑: ```python class CustomLayer(Layer): def __init__(self, arg1, arg2, **kwargs): super(CustomLayer, self).__init__(**kwargs) # 初始化代码 self.arg1 = arg1 self.arg2 = arg2 def build(self, input_shape): self.variable1 = self.add_weight(name='variable1', shape=(1,), initializer='zeros') self.variable2 = self.add_weight(name='variable2', shape=(input_shape[-1],), initializer='random_normal', trainable=True) def call(self, inputs): output = tf.matmul(inputs, self.variable2) + self.variable1 return output def get_config(self): config = super(CustomLayer, self).get_config() config.update({'arg1': self.arg1, 'arg2': self.arg2}) return config @classmethod def from_config(cls, config): return cls(**config) ``` 使用自定义层时,只需将其实例化并添加到模型中即可: ```python model = tf.keras.Sequential([ CustomLayer(arg1, arg2), tf.keras.layers.Dense(units=10, activation='softmax'), ]) ``` 以上就是使用 TensorFlow 自定义网络层的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python量化投资、代码解析与论文精读

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值