在使用tensorflow2.0搭建自定义层时,经常会将kears.Model类和keras.layers.Layer类作为父类。通常,继承Model的子类用来定义外部模型,作为训练的对象。继承Layer类来定义内部计算块。
super() 函数是用于调用父类(超类)的一个方法。super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
tf.keras.layers.Layer类
Keras 的一个中心抽象是Layer 类 。层封装了状态(层的“权重”)和从输入到输出的转换(“调用”,即层的前向传递)。所有的层对象都要继承 Layer 类。而 Layer 类继承自tf.Module类。
Layer 类的属性 | |
---|---|
trainable | 布尔型,定义层权重是否可训练 |
name | 层的名字。 |
dtype | 运算结果或权重的数值类型。默认值None为float32。也可以将权重和计算值设为不同的数值类型 |
dynamic | True:图层只能立刻地运行,并且不可用于生成静态计算图。例如,对于Tree-RNN或递归网络,或者对于使用Python控制流操纵张量的任何层 False:可以使用该层来生成静态计算图 |
定义Layer类的子类,常用下列方法:
- __init __() :使用add_weight()定义自定义图层属性,并创建不依赖于输入形状的图层状态变量。
- build(self,input_shape):此方法可用于使用add_weight()创建依赖于输入形状的权重。 __call __()将通过调用build()自动构建该层(如果尚未构建)。
- call(self,* args,** kwargs):在确保已调用build()之后,在call中调用。 call()执行将层应用于输入张量的逻辑(应将其作为参数传递)。您可以选择在call()中使用的两个保留关键字参数是:
- training(布尔值,无论呼叫处于推理模式还是训练模式)
- mask(布尔张量编码输入中的掩码时间步长,用于RNN层)
- get_config(self):返回包含用于初始化此层的配置的字典。如果键与init中的参数不同,则也重写from_config(self)。保存图层或包含该图层的模型时使用此方法。
举例
下面代码是一个基本示例:具有两个变量w和b的层,返回y = w. x + b。 它显示了如何实现build()和call()。 设置为图层属性的变量将作为图层的权重(在layer.weights中)进行跟踪。
class SimpleDense(Layer):
def __init__(self, units=32):
super(SimpleDense, self).__init__()
self.units = units
def build(self, input_shape): # 定义权重W并赋值
w_init = tf.random_normal_initializer()
self.w = tf.Variable(
initial_value=w_init(shape=(input_shape[-1], self.units),
dtype='float32'),
trainable=True)
b_init = tf.zeros_initializer()
self.b = tf.Variable(
initial_value=b_init(shape=(self.units,), dtype='float32')