Keras实现自定义层

Keras是一个高度封装的库,它的优点是可以进行快速的建模,缺点是它不处理底层运算,如张量内积等。为了弥补这个问题,Keras提供“后端引擎”来实现底层运算操作。目前Keras支持的后端引擎有tensorflow,CNTK,Theano。默认的是使用tensorflow,你可以在.keras/keras.json文件中更改backend。我们可以使用keras提供的后端来实现任意你想实现的layer。
1.首先来看下keras官方给的示例:
只有一个张量输入输出:

from keras import backend as K
from keras.layers import Layer

class MyLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel', 
                                      shape=(input_shape[1], self.output_dim),
                                      initializer='uniform',
                                      trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        return K.dot(x, self.kernel)

    def compute_output_shape(self, input_shape):
        return (input_shape[0], self.output_dim)

有多个张量输入输出时:

from keras import backend as K
from keras.layers import Layer

class MyLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        assert isinstance(input_shape, list)
        # Create a trainable weight variable for this layer.
        self.kernel = self.add_weight(name='kernel',
                                      shape=(input_shape[0][1], self.output_dim),
                                      initializer='uniform',
                                      trainable=True)
        super(MyLayer, self).build(input_shape)  # Be sure to call this at the end

    def call(self, x):
        assert isinstance(x, list)
        a, b = x
        return [K.dot(a, self.kernel) + b, K.mean(b, axis=-1)]

    def compute_output_shape(self, input_shape):
        assert isinstance(input_shape, list)
        shape_a, shape_b = input_shape
        return [(shape_a[0], self.output_dim), shape_b[:-1]]
1

 

2. 如何自定义一个层
基本的需要实现以下四个方法:
  1. __init __ (self, output_dim, **kwargs) :这个方法是用来初始化并自定义自定义层所需的属性,比如output_dim,以及一个必需要执行的super().__init __(**kwargs),这行代码是去执行Layer类中的初始化函数,当它执行了你就没有必要去管input_shape,weights,trainable等关键字参数了因为父类(Layer)的初始化函数实现了它们与layer实例的绑定。
  2. build(self, input_shape): 创建层权重的地方。你可以通过Layer类的add_weight方法来自定义并添加一个权重矩阵。这个方法一定有input_shape参数。这个方法必须设self.built = True,目的是为了保证这个层的权重定义函数build被执行过了,这个self.built其实是个标记而已,当然也可以通过调用super([MyLayer], self).build(input_shape)来完成。build这个方法是用来创建权重的,在这个函数中我们需要说明这个权重各方面的属性比如shape,初始化方式以及可训练性等信息,这也是为什么keras设计单独的一个方法来定义权重。
  3. call(self, x): 这里是编写层的功能逻辑的地方。你只需要关注传入call的第一个参数:输入张量x,而且它只能是一种形式不能是具体的变量也就是它说它不能被定义。如果你希望你的层能支持masking,我们建议直接使用官方给的Masking层即可。这个call函数就是该层的计算逻辑,或计算图了,当创建好了这个层实例后,这个实例可以使用像函数调用那样的语法来执行call函数(不懂的可以了解一下python中的__call__魔法方法)。显然,这个层的核心应该是一段符号式的输入张量到输出张量的计算过程。再次强调因为输入只是个形式,所以输入变量不能被事先定义。这个跟python中的匿名函数类似,在python中没有被赋过值的变量就是未定义的。
  4. compute_output_shape(self, input_shape):为了能让Keras内部shape的匹配检查通过,这里需要重写compute_output_shape方法去覆盖父类中的同名方法,来保证输出shape是正确的。父类Layer中的compute_output_shape方法直接返回的是input_shape这明显是不对的,所以需要我们重写这个方法。所以这个方法也是4个要实现的基本方法之一。
  当然你还可以根据需要自定义实现一些其他的方法。
 

相关参考:

https://keras.io/layers/writing-your-own-keras-layers/ 

https://blog.csdn.net/buchidanhuang/article/details/99210547

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Keras 是一个高度模块化的深度学习框架,提供了各种预定义的类型,如全连接、卷积、池化等等。然而,在某些情况下,您可能需要自定义一些实现您所需的特定功能。在 Keras 中,您可以通过继承 keras.layers.Layer 类来自定义。 以下是一个简单的例子,展示如何使用 Keras 自定义类: ```python import tensorflow as tf from tensorflow import keras class MyLayer(keras.layers.Layer): def __init__(self, output_dim, **kwargs): self.output_dim = output_dim super(MyLayer, self).__init__(**kwargs) def build(self, input_shape): self.kernel = self.add_weight(name='kernel', shape=(input_shape[1], self.output_dim), initializer='uniform', trainable=True) super(MyLayer, self).build(input_shape) def call(self, inputs): return tf.matmul(inputs, self.kernel) def compute_output_shape(self, input_shape): return (input_shape[0], self.output_dim) ``` 在上面的代码中,我们定义了一个名为 MyLayer 的自定义类。该包含一个内部实现,用于将输入张量与内部权重矩阵相乘,以产生输出张量。在这个例子中,我们使用了 TensorFlow 的 matmul 函数来实现这个操作。 我们还实现了两个必需的方法:build 和 compute_output_shape。build 方法用于初始化内部权重,并将它们添加到中。compute_output_shape 方法用于确定输出张量的形状。 要使用自定义,您可以像使用任何其他一样使用它。例如: ```python model = keras.Sequential([ MyLayer(10, input_shape=(784,)), keras.layers.Activation('softmax'), ]) ``` 在上面的代码中,我们创建了一个顺序模型,并将 MyLayer 作为第一添加到模型中。然后,我们添加了一个 softmax 激活,以便产生最终输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值