Tensorflow Keras自定义批处理规范化层,具有可在运行时更改的额外变量

Tensorflow Keras自定义批处理规范化层,具有可在运行时更改的额外变量,tensorflow,keras,keras-layer,batch-normalization,Tensorflow,Keras,Keras Layer,Batch Normalization,我通过添加self.skip变量实现了批量规范化的自定义版本,该变量以某种方式充当可训练的。以下是最低限度的代码: from tensorflow.keras.layers import BatchNormalization import tensorflow as tf # class CustomBN(tf.keras.layers.Layer): class CustomBN(BatchNormalization): def __init__(self, **kwargs):

我通过添加
self.skip
变量实现了批量规范化的自定义版本,该变量以某种方式充当
可训练的
。以下是最低限度的代码:

from tensorflow.keras.layers import BatchNormalization
import tensorflow as tf

# class CustomBN(tf.keras.layers.Layer):

class CustomBN(BatchNormalization):

    def __init__(self, **kwargs):
        super(CustomBN, self).__init__(**kwargs)
        self.skip = False

    def call(self, inputs, training=None):
        if self.skip:
            tf.print("I'm skipping")
        else:
            tf.print("I'm not skipping")
        return super(CustomBN, self).call(inputs, training)

    def build(self, input_shape):
        super(CustomBN, self).build(input_shape)
说得非常清楚,我迄今为止所做的一切是:

  • 子分类
    BatchNormalization
    :我应该子分类
    tf.keras.layers.Layer
  • 定义
    self.skip
    以更改运行时
    CustomBN
    层的行为
  • 检查
    call
    方法中的
    self.skip
    的状态以进行相应操作
  • 现在,要更改“CustomBN”层的行为,我使用

    self.model.layers[ind].skip = state
    
    其中,
    state
    True
    False
    ind
    模型中
    自定义BN
    层的索引号。 明显的问题是,
    self.skip
    的值永远不会改变。
    如果您注意到任何错误,请通知我。

    默认情况下,构建图形时将调用您所在层中的调用函数。不是以每批为基础。Keras model
    compile
    方法作为一个
    run\u急切地
    选项,该选项将导致模型在急切模式下运行(较慢),该模式将调用调用函数而无需构建图形。然而,这很可能不是您想要做的

    理想情况下,您希望更改行为的标志成为调用方法的输入。。。例如,您可以向图形中添加一个额外的输入,它就是这个
    状态
    标志,并将其传递给图层

    下面的示例说明了如何在额外参数上创建条件图

    import numpy as np
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    class MyLayerWithFlag(keras.layers.Layer):
      def call(self, inputs, flag=None):
        c_one = tf.constant([1], dtype=tf.float32)
    
        if flag is not None:
          x = tf.cond(
              flag, lambda: tf.math.add(inputs, c_one), 
              lambda: inputs)
          return x
        return inputs
    
    inputs = layers.Input(shape=(2,))
    state = layers.Input(shape=(1,), dtype=tf.bool)
    x = MyLayerWithFlag()(inputs, flag=state)
    out = layers.Lambda(tf.reduce_sum)(x)
    model = keras.Model([inputs, state], out)
    
    data = np.array([[1., 2.]])
    state = np.array([[True]])
    model.predict((data, state))
    

    默认情况下,构建图形时将调用层中的调用函数。不是以每批为基础。Keras model
    compile
    方法作为一个
    run\u急切地
    选项,该选项将导致模型在急切模式下运行(较慢),该模式将调用调用函数而无需构建图形。然而,这很可能不是您想要做的

    理想情况下,您希望更改行为的标志成为调用方法的输入。。。例如,您可以向图形中添加一个额外的输入,它就是这个
    状态
    标志,并将其传递给图层

    下面的示例说明了如何在额外参数上创建条件图

    import numpy as np
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    class MyLayerWithFlag(keras.layers.Layer):
      def call(self, inputs, flag=None):
        c_one = tf.constant([1], dtype=tf.float32)
    
        if flag is not None:
          x = tf.cond(
              flag, lambda: tf.math.add(inputs, c_one), 
              lambda: inputs)
          return x
        return inputs
    
    inputs = layers.Input(shape=(2,))
    state = layers.Input(shape=(1,), dtype=tf.bool)
    x = MyLayerWithFlag()(inputs, flag=state)
    out = layers.Lambda(tf.reduce_sum)(x)
    model = keras.Model([inputs, state], out)
    
    data = np.array([[1., 2.]])
    state = np.array([[True]])
    model.predict((data, state))
    

    我使用
    Sequential
    model
    kerasapi实现了
    model
    ,这不会改变结果。在设置
    model.layers[ind].skip=state
    之后,我也编译了模型,这同样没有什么区别!我使用
    Sequential
    model
    kerasapi实现了
    model
    ,这不会改变结果。在设置
    model.layers[ind].skip=state
    之后,我也编译了模型,这同样没有什么区别!