keras中文文档
https://keras.io/zh/layers/recurrent/
keras源码分析
https://www.jianshu.com/p/8dcddbc1c6d4
实现自己的Keras层
https://blog.csdn.net/DawnRanger/article/details/78307244
所有keras层的基类:Layer
用到的装饰器:
@property 让类函数能像类变量一样操作
@interfaces.legacy_xxx_support 让函数支持keras 1.x的 API
@classmothod 类函数,属于整个类,类似于C++/JAVA中的静态函数。类方法有类变量cls传入,从而可以用cls做一些相关的处理。子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。既可以在类内部使用self访问,也可以通过实例、类名访问。
@staticmethod 将外部函数集成到类体中,既可以在类内部使用self访问,也可以通过实例、类名访问。基本上等同于一个全局函数。
magic函数:
__call__ 让类的实例可以像函数一样调用,正是python的这种特性让我们可以像这样进行层之间的连接:
inputs = Input(shape=(784,))
# 前面的Dense(64, activation='relu')生成了类Dense的一个实例
# 后面的(input)将调用类Dense的__call__函数
x = Dense(64, activation='relu')(inputs)
InputSpec: 确定层的ndim,dtype,shape,每一层都应有一个input_spec属性,保存InputSpec的实例的list(每一个输入tensor都对应一个)
重点关注以下函数
1. add_weight
每层的参数通过这个函数来设定。可以看到它最终调用的是 K.variable 来生成变量,打开 keras/backend/tensorflow_backend.py
可以看到它生成变量的方式:
v = tf.Variable(value, dtype=tf.as_dtype(dtype), name=name)
keras不使用tf.get_variable的方式生成变量,可见keras在设计时就根本没有考虑到变量共享,从之前的经验来看,要用keras设计多GPU程序是非常棘手的。(要想让Keras支持多GPU并行,必须从这一步开始修改代码,而这里已经是keras非常底层的代码了。)
2. call / __call__
call是最重要的函数,它用于实现层的功能,子类必须实现。
魔法函数 __call__ 会将收到的输入传递给 call 函数,然后调用 call 函数实现具体的功能。
3. comput_output_shape
根据input_shape 计算输出的shape,子类必须实现。用于自动推断下一层的输入尺寸。
4. build
用来创建当前层的weights,子类必须实现。
5. get_config / from_config
get_config 返回一个字典,获取当前层的参数信息。
from_config 使用根据参数生成一个新的层。代码只有一行:
@classmethod
def from_config(cls, config):
return cls(**config)
可见from_config是一个classmethod,根据传入的参数,使用当前类的构造函数来生成一个实例。
通过子类调用时,cls是子类而不是基类Layer。
二、实现自己的keras层
官方文档的说明:
对于简单的定制操作,我们或许可以通过使用layers.core.Lambda层来完成。
但对于任何具有可训练权重的定制层,你应该自己来实现。
build(input_shape):这是定义权重的方法,可训练的权应该在这里被加入列表self.trainable_weights中。
其他的属性还包括self.non_trainabe_weights(列表)和self.updates(需要更新的形如(tensor, new_tensor)的tuple的列表)。
可参考BatchNormalization层的实现来学习如何使用上面两个属性。
这个方法必须设置self.built = True,可通过调用super([layer],self).build()实现call(x):
这是定义层功能的方法,除非你希望你写的层支持masking,否则你只需要关心call的第一个参数:输入张量
compute_output_shape(input_shape):如果你的层修改了输入数据的shape,你应该在这里指定shape变化的方法,这个函数使得Keras可以做自动shape推断
原文:https://blog.csdn.net/DawnRanger/article/details/78307244