【问题标题】:How to update weights in Stochastic Weight Averaging (SWA) on tensorflow?如何在张量流上更新随机权重平均(SWA)中的权重?
【发布时间】:2021-05-06 03:05:09
【问题描述】:

我对如何实现 tfa 的 SWA optimizer 感到困惑。这里有两点:

  1. 当您查看文档时,它会将您指向 [this] 模型平均教程。该教程使用 tfa.callbacks.AverageModelCheckpoint,它允许您
  • 将移动平均权重分配给模型并保存。
  • (或)保留旧的非平均权重,但保存的模型使用平均权重。

拥有一个独特的 ModelCheckpoint 可以让您保存移动平均权重(而不是当前权重)是有意义的。但是 - 似乎 SWA 应该管理权重平均。这让我想设置update_weights=False

这是正确的吗?本教程使用update_weights=True

  1. documentation 中有一条关于 SWA 未更新 BN 层的说明。按照here 的建议,我这样做了,
# original training
model.fit(...)
# updating weights from final run 
optimizer.assign_average_vars(model.variables)
# batch-norm-hack: lr=0 as suggested https://stackoverflow.com/a/64376062/607528
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0),
    loss=loss,
    metrics=metrics)
model.fit(
    data,
    validation_data=None,
    epochs=1,
    callbacks=final_callbacks)

在保存我的模型之前。

这对吗?

谢谢!

【问题讨论】:

    标签: python tensorflow machine-learning deep-learning tensorflow2.0


    【解决方案1】:

    处理批范数的最简单方法如下: 首先,遍历模型中的所有层并重置批范数层中的移动均值和移动方差(在我的示例中,我假设批范数层以“bn”结尾):

    for l in model.layers:
        if l.name.split('_')[-1] == 'bn': # e.g. conv1_bn
           l.moving_mean.assign(tf.zeros_like(l.moving_mean))
           l.moving_variance.assign(tf.ones_like(l.moving_variance))
    

    之后,运行您的模型一个时期并将训练设置为 true 以更新移动平均值和方差:

    count = 0
    for x,_ in dataset_train:
        _ = model(x, training = True)
        count += 1
        if count > steps_per_epoch:
           break
    

    【讨论】:

      【解决方案2】:

      两种方法可以做到这一点,第一种是您在保存之前手动更新权重,例如文档中的example

      import tensorflow as tf
      import tensorflow_addons as tfa
      
      model = tf.Sequential([...])
      opt = tfa.optimizers.SWA(
              tf.keras.optimizers.SGD(lr=2.0), 100, 10)
      model.compile(opt, ...)
      model.fit(x, y, ...)
      
      # Update the weights to their mean before saving
      opt.assign_average_vars(model.variables)
      
      model.save('model.h5')
      

      如果您设置了update_weights = True,则第二个选项是通过 AverageModelCheckpoint 更新权重。正如协作笔记本example 所示

      avg_callback = tfa.callbacks.AverageModelCheckpoint(filepath=checkpoint_dir, 
                                                          update_weights=True)
      ...
      
      #Build Model
      model = create_model(moving_avg_sgd)
      
      #Train the network
      model.fit(fmnist_train_ds, epochs=5, callbacks=[avg_callback])
      

      注意AverageModelCheckpoint 在保存模型之前也会从source code 调用assign_average_vars

      def _save_model(self, epoch, logs):
          optimizer = self._get_optimizer()
          assert isinstance(optimizer, AveragedOptimizerWrapper)
      
          if self.update_weights:
              optimizer.assign_average_vars(self.model.variables)
              return super()._save_model(epoch, logs)
          ...
      

      【讨论】:

      • 谢谢!但我很困惑。请注意,在我的问题中,我会提出您的两个建议。 opt.assign_average_vars(model.variables) 会更新权重,回调会执行相同的操作,但会在整个训练过程中进行。为了澄清我的问题:(1)在训练期间我应该有update_weights=True 还是由 SWA 优化器管理? (2) 我不认为assign_average_vars 在平均后不使用更新的权重来处理批处理规范权重(请参阅文档中的注释),我想知道我的 lr=0 拟合是否是正确的修复
      • 这就是说这让我意识到AverageModelCheckpoint 可能没有正确处理批处理规范层?
      • 从@Simon Larsson 的实现开始,在last epoch 上将学习率更新为zero,模型权重为swareset batch norm,然后运行最后一个epoch。当训练结束时,它也会恢复批量规范
      • 遵循该指南,您的实现似乎只是在运行最后的训练步骤之前错过了恢复批量规范。我建议你试试 Simon Larsson 的Keras SWA
      • 感谢 miguel - 不知何故我的问题被遗漏了 - 我的实现确实做到了:model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0),loss=loss,metrics=metrics) model.fit(data,validation_data=None,epochs=1,...)
      猜你喜欢
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 2017-06-19
      • 2021-10-13
      • 1970-01-01
      相关资源
      最近更新 更多