【问题标题】:BatchNormalization in KerasKeras 中的 BatchNormalization
【发布时间】:2018-10-14 07:55:25
【问题描述】:

如何在 keras BatchNormalization 中更新移动均值和移动方差?

我在 tensorflow 文档中找到了这个,但我不知道在哪里放置 train_op 或如何使用 keras 模型:

update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
        with tf.control_dependencies(update_ops):
            train_op = optimizer.minimize( loss )

我发现没有帖子说明如何使用 train_op 以及是否可以在 model.compile 中使用它。

【问题讨论】:

  • 你想做什么?通常,您不需要为 BatchNormalization 做任何事情就可以在 Keras 中工作。
  • 我只是想使用 BatchNormalization。让我感到困惑的是 Tensorflow 和 Keras 之间的差异,所以我不确定我是否真的不需要做任何其他事情(除了确保在验证期间关闭 BatchNormalization),或者我是否必须手动更新移动平均值和差异。
  • @MatiasValdenegro 从optimizer.minimize(loss) 看来,他正在尝试手动执行梯度下降步骤(而不是使用更高级别的 API 来驱动拟合)。 optimizer.minimize()(例如,使用 'AdamOptimizer' 或 'GradientDescentOptimizer')将使用梯度下降来更新一步的常规权重,但它不会对批量范数均值和方差做任何事情。
  • 对我来说,如果我使用batch_normed = tf.keras.layers.BatchNormalization()(hidden, training=True)update_ops 是空的。所以似乎没有更新移动平均线(例如batch_normalization/moving_mean

标签: tensorflow keras batch-normalization


【解决方案1】:

如果您使用 BatchNormalization 层,则无需手动更新移动均值和方差。 Keras 负责在训练期间更新这些参数,并在测试期间保持它们不变(通过使用 model.predictmodel.evaluate 函数,与 model.fit_generator 和朋友一样)。

Keras 还跟踪学习阶段,以便在训练和验证/测试期间运行不同的代码路径。

【讨论】:

  • 如果您使用带有训练和验证集的 model.fit_generator 怎么办?
  • @A.Hendry 同样,我只是忘了提。
  • @MatiasValdenegro 我怀疑这行得通。我在我的训练循环中打印出变量batch_normalization/moving_mean 的前两个元素,该循环也使用optimizer.minimize(loss),它们永远不会改变。我正在使用tensorflow.train.AdamOptimizer 并手动运行optimizer.minimize(loss) 来反向传播权重更新。我怀疑一个更高级别的 API(例如 tensorflow.keras.models.Model.fit())除了反向传播之外正在做一些事情来更新批处理规范统计信息,并且仅仅使用 optimizer.minimize(loss) 就缺少“一些东西”。
  • @Syncopated 我不知道你在说什么,我的回答是关于使用 Keras,看来你没有使用纯 Keras。
  • @MatiasValdenegro 看到问题被标记为'tensorflow'和'keras',我说的是在tensorflow中使用keras,但是看到作者似乎已经接受了答案,也许他不是真的在谈论 tensorflow。
【解决方案2】:

如果您只需要使用一些新值更新现有模型的权重,则可以执行以下操作:

w = model.get_layer('batchnorm_layer_name').get_weights()
# Order: [gamma, beta, mean, std]
for j in range(len(w[0])):
    gamma = w[0][j]
    beta = w[1][j]
    run_mean = w[2][j]
    run_std = w[3][j]
    w[2][j] = new_run_mean_value1
    w[3][j] = new_run_std_value2

model.get_layer('batchnorm_layer_name').set_weights(w)

【讨论】:

    【解决方案3】:

    这个问题有两种解释:第一种是假设目标是使用高级培训 api,这个问题由 Matias Valdenegro 回答。

    第二个 - 如 cmets 中所讨论的 - 是否可以使用标准 tensorflow 优化器的批量标准化,如此处 keras a simplified tensorflow interface 和“收集可训练权重和状态更新”部分所述。如前所述,更新操作可以在 layer.updates 中访问,而不是在 tf.GraphKeys.UPDATE_OPS 中,事实上,如果你在 tensorflow 中有一个 keras 模型,你可以使用标准的 tensorflow 优化器和像这样的批量标准化进行优化

    update_ops  = model.updates
    with tf.control_dependencies(update_ops):
         train_op = optimizer.minimize( loss )
    

    然后使用 tensorflow 会话来获取 train_op。要区分批归一化层的训练和评估模式,您需要输入 keras 引擎的学习阶段状态(请参阅上面给出的同一 tutorial page 上的“训练和测试期间的不同行为”)。例如,这将像这样工作

    ... 
    # train
    lo, _ = tf_sess.run(fetches=[loss, train_step],
                        feed_dict={tf_batch_data: bd,
                                   tf_batch_labels: bl,
                                   tensorflow.keras.backend.learning_phase(): 1})
    
    ...
    
    # eval
    lo = tf_sess.run(fetches=[loss],
                        feed_dict={tf_batch_data: bd,
                                   tf_batch_labels: bl,
                                   tensorflow.keras.backend.learning_phase(): 0})
    
    

    我在 tensorflow 1.12 中尝试过这个,它适用于包含批量标准化的模型。鉴于我现有的 tensorflow 代码以及接近 tensorflow 版本 2.0,我很想自己使用这种方法,但鉴于 tensorflow 文档中没有提到这种方法,我不确定这是否会得到长期支持,我终于决定不使用了,多投入一点,改代码来使用高级api。

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 2018-01-08
      • 2018-05-14
      • 2017-06-08
      • 2021-08-30
      • 2019-03-04
      • 2021-03-16
      • 1970-01-01
      • 2020-05-21
      相关资源
      最近更新 更多