Tensorflow2.0与Keras如何构建个性化神经网络模型?
摘要:Keras是基于Tensorflow(以前还可以基于别的底层张量库,现在已并入TF)的高层API库。它帮我们实现了一系列经典的神经网络层(全连接层、卷积层、循环层等),以及简洁的迭代模型的接口,让我们能在模型层面写代码,从而不用仔细考虑模型
Keras是基于Tensorflow(以前还可以基于别的底层张量库,现在已并入TF)的高层API库。它帮我们实现了一系列经典的神经网络层(全连接层、卷积层、循环层等),以及简洁的迭代模型的接口,让我们能在模型层面写代码,从而不用仔细考虑模型各层张量之间的数据流动。
但是,当我们有了全新的想法,想要个性化模型层的实现时,仅靠Keras的高层API是不能满足这一要求的。下面记录使用TF与Keras快速搭建神经网络模型。
自定义网络层
实现往Keras的Model类中添加自定义层,有两种方式:
1、定义Lambda层。
2、继承Layer类。
lambda层
Lambda层仅能对输入做固定的变换,并不能定义可以通过反向传播训练的参数(通过Keras的fit训练),因此能实现的东西较少。以下代码实现了Dropout的功能:
from keras import backend as K
from keras import layers
def my_layer(x):
mask = K.random_binomial(K.shape(x),0.5)
return x*mask*2
x = layers.Lambda(my_layer)(x)
其中my_layer函数是自定义层要实现的操作,传递参数只能是Lambda层的输入。定义好函数后,直接在layers.Lambda中传入函数对象即可。实际上,这些变换不整合在lambda层中而直接写在外面也是可以的:
from keras import backend as K
from keras import layers
x = layers.Dense(500,activation='relu')(x)
mask = K.random_binomial(K.shape(x),0.5)
x = x*mask*2
更新:这样做在Keras最新版本已经不支持了,只支持Lambda层了。
以上实现Dropout只是作举例,你可以以同样的方式实现其它的功能。
继承layer类
如果你想自定义可以训练参数的层,就需要继承实现Keras的抽象类Layer。主要实现以下三个方法:
1、__init__(self, *args, **kwargs):构造函数,在实例化层时调用。此时还没有添加输入,也就是说此时输入规模未知,但可以定义输出规模等与输入无关的变量。类比于Dense层里的units、activations参数。
2、build(self, input_shape):在添加输入时调用(__init__之后),且参数只能传入输入规模input_shape。此时输入规模与输出规模都已知,可以定义训练参数,比如全连接层的权重w和偏执b。
3、call(self, *args, **kwargs):编写层的功能逻辑。
