TensorFlow2.0学习笔记-4.模型的自定义

4.模型的自定义

4.1.自定义层

使用的主要数据结构是Layer
实现自定义层的最佳方法是扩展tf.keras.layers.Layer类并实现:
• __init__ :可以在其中进行所有与输入无关的初始化,定义相关的层
• build: 知道输入张量的形状并可以进行其余的初始化
• call: 在这里进行前向传播
注意:不一定需要在build中创建变量时,也可以在__init__中创建它们。

 

tf.keras.Model和tf.keras.layers.Layer有什么区别和联系?
• 通过继承 tf.keras.Model 编写自己的模型类
• 通过继承 tf.keras.layers.Layer 编写自己的层
• tf.keras中的模型和层都是继承tf.Module实现的
• tf.keras.Model继承tf.keras.layers.Layer实现的

 

tf.Module: 定位为一个轻量级的状态容器,因为可以收集变量,所以这个类型可以用来建模,配合tf.GradientTape使用。

 

自定义一个线性回归模型

使用鸢尾花数据集

from sklearn import datasets

iris = datasets.load_iris()

 

data = iris.data

target = iris.target

 

data.shape   # x

(150, 4)

target.shape #y

(150,)

 

方法1:最基础的方法

import tensorflow as tf

#自定义全连接层

class Linear(tf.keras.layers.Layer):

 

    def __init__(self, units=1, input_dim=4):

        super(Linear, self).__init__() #

        w_init = tf.random_normal_initializer()

        self.w = tf.Variable(initial_value=w_init(shape=(input_dim, units), dtype='float32'),  trainable=True)

        b_init = tf.zeros_initializer()

        self.b = tf.Variable(initial_value=b_init(shape=(units,),dtype='float32'),trainable=True)

 

    def call(self, inputs):

        return tf.matmul(inputs, self.w) + self.b

 

x = tf.constant(data) #(150,4)

linear_layer = Linear(units = 1, input_dim=4) #()

y = linear_layer(x)

print(y.shape) #(150,1)

(150, 1)

 

方法2:使用self.add_weight创建变量

class Linear(tf.keras.layers.Layer):

 

    def __init__(self, units=1, input_dim=4):

        super(Linear, self).__init__()

        self.w = self.add_weight(shape=(input_dim, units),

                                 initializer='random_normal',

                                 trainable=True)

        self.b = self.add_weight(shape=(units,),

                                 initializer='zeros',

                                 trainable=True)

 

    def call(self, inputs):

        return tf.matmul(inputs, self.w) + self.b

 

x = tf.constant(data)

linear_layer = Linear(units = 1, input_dim=4)

y = linear_layer(x)

print(y.shape)

(150, 1)

 

方法三:build函数中创建变量

class Linear(tf.keras.layers.Layer):

 

    def __init__(self, units=32):

        super(Linear, self).__init__()

        self.units = units

 

    def build(self, input_shape): #(150,4)

        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)

        super(Linear,self).build(input_shape)

 

    def call(self, inputs):

        return tf.matmul(inputs, self.w) + self.b

    

x = tf.constant(data) #150*4

linear_layer = Linear(units = 1)

y = linear_layer(x)

print(y.shape)

(150, 1)

 

添加不可训练的参数

class Linear(tf.keras.layers.Layer):

 

    def __init__(self, units=32):

        super(Linear, self).__init__()

        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=False)

        super(Linear,self).build(input_shape)

 

    def call(self, inputs):

        return tf.matmul(inputs, self.w) + self.b

    

x = tf.constant(data)

linear_layer = Linear(units = 1)

y = linear_layer(x)

print(y.shape)

(150, 1)

 

# 打印所有参数、不可训练参数、可训练参数

print('weight:', linear_layer.weights)

print('non-trainable weight:', linear_layer.non_trainable_weights)

print('trainable weight:', linear_layer.trainable_weights)

weight: [<tf.Variable 'linear_4/Variable:0' shape=(4, 1) dtype=float32, numpy=

array([[ 0.00276536],

       [-0.07950259],

       [ 0.01646506],

       [ 0.00197834]], dtype=float32)>, <tf.Variable 'linear_4/Variable:0' shape=(1,) dtype=float32, numpy=array([0.00255805], dtype=float32)>]

non-trainable weight: [<tf.Variable 'linear_4/Variable:0' shape=(1,) dtype=float32, numpy=array([0.00255805], dtype=float32)>]

trainable weight: [<tf.Variable 'linear_4/Variable:0' shape=(4, 1) dtype=float32, numpy=

array([[ 0.00276536],

       [-0.07950259],

       [ 0.01646506],

       [ 0.00197834]], dtype=float32)>]

 

自定义层的注意事项

如果需要保存模型,则在自定义网络层时需要重写get_config 方法

我们主要看传入__init__接口时有哪些配置参数,然后在get_config内一一的将它们转为字典键值并且返回使用

get_config的作用:获取该层的参数配置,以便模型保存时使用

自定义层的biuld 中创建初始矩阵时, 需要添加name属性

我们在实现自定义网络层时,最好统一在初始化时传入可变参数**kwargs,这是因为在model推理时,有时我们需要对所有构成该模型的网络层进行统一的传参。

import tensorflow as tf

#Dense

class MyDense(tf.keras.layers.Layer):

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

        self.units = units

        super(MyDense, self).__init__(**kwargs)

 

    #build方法一般定义Layer需要被训练的参数。    

    def build(self, input_shape):

        self.w = self.add_weight(shape=(input_shape[-1], self.units),

                                 initializer='random_normal',

                                 trainable=True,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值