【问题标题】:Tensorflow 2.0 Keras BatchNorm: how to update the online params in custom training?Tensorflow 2.0 Keras BatchNorm:如何更新自定义训练中的在线参数?
【发布时间】:2019-10-02 11:25:22
【问题描述】:

如何在不使用任何 keras.compile 方法的情况下训练批处理规范层?通常,层具有可访问的损失。这里的loss方法是空的。

更新:

似乎对此有很多困惑,甚至 BatchNorm 的实现方式也很混乱。

首先,只有通过训练在线参数(在 training=False 模式下使用)来缩放和转移特征:在 training=True 模式下调用层。而且,如果您从不想使用批处理规范化的“批处理”部分(即,您只想要一个在线规范化器,它可以通过 Normal log-prob loss 进行自我训练,那么您基本上无法在一次调用 AFAIK 中做到这一点。

使用 training=False 调用层不会更新参数。用 training=True 调用它会更新参数,但随后你会得到批量标准化层(不使用在线 loc 和 scale)。

import tensorflow as tf

class Model(tf.keras.models.Model):
    def __init__(self):
        super().__init__()
        self.dense = tf.keras.layers.Dense(4)
        self.bn = tf.keras.layers.BatchNormalization()
    def call(self, x, training=False):
        x = self.dense(x)
        x = self.bn(x, training=training)
        return x

model = Model()    
x = 10 * np.random.randn(30, 4).astype(np.float32)

print(tf.math.reduce_std(model(x)))
tf.keras.backend.set_learning_phase(1)
print(tf.math.reduce_std(model(x)))
print(tf.math.reduce_std(model(x)))
tf.keras.backend.set_learning_phase(0)
print(tf.math.reduce_std(model(x)))
print(tf.math.reduce_std(model(x)))


tf.Tensor(9.504262, shape=(), dtype=float32)
tf.Tensor(0.99999136, shape=(), dtype=float32)
tf.Tensor(0.99999136, shape=(), dtype=float32)
tf.Tensor(5.4472375, shape=(), dtype=float32)
tf.Tensor(5.4472375, shape=(), dtype=float32)

更新:

显示 keras 层有时会有损失(当子任务存在时,例如规则化):

In [335]: l = tf.keras.layers.Dense(8, kernel_regularizer=tf.keras.regularizers.L1L2())

In [336]: l(np.random.randn(2, 4))

Out[336]:
<tf.Tensor: id=2521999, shape=(2, 8), dtype=float32, numpy=
array([[ 1.1332406 ,  0.32000083,  0.8104123 ,  0.5066328 ,  0.35904446, -1.4265257 ,  1.3057183 ,  0.34458983],
       [-0.23246719, -0.46841025,  0.9706465 ,  0.42356712,  1.705613  , -0.08619405, -0.5261058 , -1.1696107 ]], dtype=float32)>

In [337]: l.losses
Out[337]: [<tf.Tensor: id=2522000, shape=(), dtype=float32, numpy=0.0>]

In [338]: l = tf.keras.layers.Dense(8)

In [339]: l(np.random.randn(2, 4))

Out[339]:
<tf.Tensor: id=2522028, shape=(2, 8), dtype=float32, numpy=
array([[ 1.0674231 , -0.13423748,  0.01775402,  2.5400681 , -0.53589094,  1.4460006 , -1.7197075 ,  0.3285858 ],
       [ 2.2171447 , -1.7448915 ,  0.4758569 ,  0.58695656,  0.32054698,  0.7813705 , -2.3022552 ,  0.44061095]], dtype=float32)>

In [340]: l.losses
Out[340]: []

【问题讨论】:

  • Keras 层从来没有损失过,所以不知道你在说什么概念,你能澄清一下吗?
  • Keras 层有损失。将粘贴简单的代码以在 udpate 中显示。
  • 批量规范有一个必须训练的损失......即训练=假的情况,其中学习的参数用于定位移位和缩放特征。如果它通过侧通道在线更新进行训练,应该在文档中明确说明。
  • 不,Batch norm根本没有损失。您可能正在寻找的是批量规范总体均值和标准的更新操作
  • 嗯,好的,这就是我要找的。似乎很奇怪,他们为层丢失实现了“操作”。例如,如果你用双射器实现这种东西,你可能会使用损失,但也许批量规范出现在所有重构之前?

标签: keras tensorflow2.0 batchnorm


【解决方案1】:

BatchNorm 确实训练,但没有损失。它只是在加权移动平均线中跟踪连续批次的平均值和标准差。不涉及损失/梯度。

【讨论】:

  • 在线更新在概念上是一个损失梯度。我们应该更新文档以明确声明该层不是基于“keras loss”的,并通过自定义更新操作实现它自己的子任务更新。我认为对于我们这些来自 TF2 和 TFP(双射器等)的人来说,这变得特别不自然。例如,RealNVP 在结构上与 training=False 模式下的批处理规范非常相似。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-27
  • 2020-04-13
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
相关资源
最近更新 更多