• 【提分trick】SWA(随机权重平均)和EMA(指数移动平均)


    1. SWA随机权重平均

     1.1步骤

    1.2代码

    2.EMA指数移动平均

    2.1步骤

    2.2代码

     3.总结


    kaggle比赛中,不管是目标检测任务、语义分割任务中,经常能看到SWA(Stochastic Weight Averaging)和EMA(Exponential Moving Average)的身影,今天就来一起学习下。

    1. SWA随机权重平均

    SWA随机权重平均:在优化的末期取k个优化轨迹上的checkpoints,平均他们的权重,得到最终的网络权重,这样就会使得最终的权重位于flat曲面更中心的位置,缓解权重震荡问题,获得一个更加平滑的解,相比于传统训练有更泛化的解。

     1.1步骤

    1.给定超参数:

    • 循环周期c,代表训练c步就使用SWA进行一次权重平均
    • 学习率 α1,α2 ,即周期学习率的上界和下界,论文的实验使用的周期性学习率如下图

    2.然后,按照正常的SGD标准流程进行训练,每训练c步,就平均一次权重

    3.最后,使用平均的权重 wSWA 权重进行推理。

    1.2代码

    1. import torch
    2. import torch.nn as nn
    3. def apply_swa(model: nn.Module,
    4. checkpoint_list: list,
    5. weight_list: list,
    6. strict: bool = True):
    7. """
    8. :param model:
    9. :param checkpoint_list: 要进行swa的模型路径列表
    10. :param weight_list: 每个模型对应的权重
    11. :param strict: 输入模型权重与checkpoint是否需要完全匹配
    12. :return:
    13. """
    14. checkpoint_tensor_list = [torch.load(f, map_location='cpu') for f in checkpoint_list]
    15. for name, param in model.named_parameters():
    16. try:
    17. param.data = sum([ckpt['model'][name] * w for ckpt, w in zip(checkpoint_tensor_list, weight_list)])
    18. except KeyError:
    19. if strict:
    20. raise KeyError(f"Can't match '{name}' from checkpoint")
    21. else:
    22. print(f"Can't match '{name}' from checkpoint")
    23. return model

    2.EMA指数移动平均

    EMA指数移动平均:shadow权重是通过历史的模型权重指数加权平均数来累积的,每次shadow权重的更新都会受上一次shadow权重的影响,所以shadow权重的更新都会带有前几次模型权重的惯性,历史权重越久远,其重要性就越小,这样可以使得权重更新更加平滑。

    •  w_{shadow}为EMA权重,也被称为影子权重;
    • \alpha为衰退率,一般为0.999或0.9999;
    • w为模型权重

    从上述公式来看,shadow权重的更新大部分由累积的权重决定,小部分由当前权重决定。 

    2.1步骤

    1. 创建EMA平滑的shadow权重(对应EMA对象初始化和register方法)
    2. 按照正常的训练流程,反向传播更新模型权重
    3. 更新模型权重之后,再执行EMA平滑,更新shadow权重(对应update方法)
    4. 重复2-3步,直到valid阶段
    5. 备份模型权重,加载shadow权重,使用shadow权重进行模型的valid工作(对应apply_shadow方法)
    6. 使用shadow权重作为模型权重,保存模型
    7. 恢复模型权重(对应restore方法),继续重复以上步骤2-7。

    2.2代码

    1. import torch
    2. import torch.nn as nn
    3. from torch.utils.data import DataLoader
    4. class EMA:
    5. def __init__(self, model: nn.Module,
    6. decay: float = 0.999):
    7. self.model = model
    8. self.decay = decay
    9. self.shadow = {}
    10. self.backup = {}
    11. def register(self):
    12. """创建shadow权重"""
    13. for name, param in self.model.named_parameters():
    14. if param.requires_grad:
    15. self.shadow[name] = param.data.clone()
    16. def update(self):
    17. """EMA平滑操作,更新shadow权重"""
    18. for name, param in self.model.named_parameters():
    19. if param.requires_grad:
    20. assert name in self.shadow
    21. new_average = (1.0 - self.decay) * param.data + self.decay * self.shadow[name]
    22. self.shadow[name] = new_average.clone()
    23. def apply_shadow(self):
    24. """使用shadow权重作为模型权重,并创建原模型权重备份"""
    25. for name, param in self.model.named_parameters():
    26. if param.requires_grad:
    27. assert name in self.shadow
    28. self.backup[name] = param.data
    29. param.data = self.shadow[name]
    30. def restore(self):
    31. """恢复模型权重"""
    32. for name, param in self.model.named_parameters():
    33. if param.requires_grad:
    34. assert name in self.backup
    35. param.data = self.backup[name]
    36. self.backup = {}

     3.总结

    1. EMA需要在每步训练时,同步更新shadow权重,但其计算量与模型的反向传播相比,成本很小,因此实际上并不会拖慢很对模型的训练进度;
    2. SWA可以在训练结束,进行手动加权,完全不增加额外的训练成本;
    3. 实际使用两者可以配合使用,可以带来一点模型性能提升。

    整理不易,欢迎一键三连!!! 

  • 相关阅读:
    手机定屏死机问题操作指南
    Selenium4+python被单独定义<div>的动态输入框和二级下拉框要怎么定位?
    autojs修改顶部标题栏颜色
    Linux web访问日志在什么目录
    【自然语言处理(NLP)】基于预训练模型的机器阅读理解
    halcon-思路整理
    天龙八部科举答题问题和答案(全7/8)
    项目管理证书 PMP 的含金量高吗?
    linux 归档和压缩文件和目录
    【JS 构造|原型|原型链|继承(圣杯模式)|ES6类语法】下篇
  • 原文地址:https://blog.csdn.net/qq_38308388/article/details/127687847