批量归一化:Batch Normalization层 原理+Pytorch实现

2023-05-16

一、BN层概念明晰

BN层存在的意义:让较深的神经网络的训练变得更加容易。

BN层的工作内容:利用小批量数据样本的均值和标准差,不断调整神经网络中间输出,使整个神经网络在各层的中间输出的数值更加稳定。

BN层在Net中的运算方式:考虑图像首个CBA层,[3*416*416]经过16个通道的3*3卷积后变为[16*416*416],则之后的BN层会有16个\gamma -\beta组,每个通道都对应一组。train时使用Batch内归一化,同时计算滑动平均;test时会用滑动平均中存的值。

BN层注意事项:训练模式和预测模式计算结果不同。

训练模式下:数据是成批的,可以进行批内求均值、求方差,进而得到归一化结果,最后乘以拉伸参数(scale—\gamma)和偏移参数(shift—\beta)得到BN层结果;同时,训练过程中还会对整个数据集的全局均值和全局方差进行移动平均估计和记录。

预测模式下:样本都是单张送入,无法使用Batch方式计算均值和方差,此时使用训练过程中记录的全局均值和全局方差进行归一化,之后用学习到的拉伸参数(scale—\gamma)和偏移参数(shift—\beta)得到BN层结果。

注:Pytorch的网络搭建好了之后需要进行模式选择,也就是model.train()或者model.eval()。model.eval()预测时会自动把BN和DropOut层固定住,不会取平均,而是使用训练好的值。

二、Pytorch简易实现代码

《动手学深度学习》中的原理示例型代码,帮助理解网络层搭建过程:

def batch_norm(is_training, X, gamma, beta, moving_mean, moving_var, eps, momentum):
    # 预测模式
    if not is_training:
        X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)  # 直接使用传入的移动平均所得的均值和方差
    # 训练模式
    else:
        assert len(X.shape) in (2, 4)  # 样本数为2,特征数为4
        if len(X.shape) == 2:  # 使用全连接层的情况,计算特征维上的均值和方差,数据维度1*4
            mean = X.mean(dim=0)
            var = ((X - mean) ** 2).mean(dim=0)
        else:
            # 使用二维卷积层的情况,计算通道维上(axis=1)的均值和方差。这里我们需要保持
            # X的形状以便后面可以做广播运算
            mean = X.mean(dim=0, keepdim=True).mean(dim=2, keepdim=True).mean(dim=3, keepdim=True)
            var = ((X - mean) ** 2).mean(dim=0, keepdim=True).mean(dim=2, keepdim=True).mean(dim=3, keepdim=True)

        # 训练模式下用当前的均值和方差做标准化
        X_hat = (X - mean) / torch.sqrt(var + eps)

        # 更新移动平均的均值和方差
        moving_mean = momentum * moving_mean + (1.0 - momentum) * mean
        moving_var = momentum * moving_var + (1.0 - momentum) * var

    Y = gamma * X_hat + beta  # 拉伸和偏移
    return Y, moving_mean, moving_var


class BatchNorm(nn.Module):
    def __init__(self, num_features, num_dims):
        super(BatchNorm, self).__init__()
        if num_dims == 2:
            shape = (1, num_features)
        else:
            shape = (1, num_features, 1, 1)
        # 参与求梯度和迭代的拉伸和偏移参数,分别初始化成1和0
        self.gamma = nn.Parameter(torch.ones(shape))
        self.beta = nn.Parameter(torch.zeros(shape))
        # 不参与求梯度和迭代的变量,全在内存上初始化成0
        self.moving_mean = torch.zeros(shape)
        self.moving_var = torch.zeros(shape)

    def forward(self, X):
        # 如果X不在内存上,将moving_mean和moving_var复制到X所在显存上
        if self.moving_mean.device != X.device:
            self.moving_mean = self.moving_mean.to(X.device)
            self.moving_var = self.moving_var.to(X.device)
        # 保存更新过的moving_mean和moving_var, Module实例的traning属性默认为true, 调用.eval()后设成false
        Y, self.moving_mean, self.moving_var = batch_norm(self.training,X, self.gamma, self.beta, self.moving_mean,self.moving_var, eps=1e-5, momentum=0.9)
        return Y

三、Pytorch中BN网络搭建

此例是Pytorch的YOLO实现中网络搭建和参数load方法:

搭建:

modules.add_module(f"batch_norm_{module_i}", nn.BatchNorm2d(filters, momentum=0.9, eps=1e-5))

数据加载:(我的天这个好麻烦)

ptr = 0
for i, (module_def, module) in enumerate(zip(self.module_defs, self.module_list)):
    if i == cutoff:
        break
    if module_def["type"] == "convolutional":
        conv_layer = module[0]
        if module_def["batch_normalize"]:
            # Load BN bias, weights, running mean and running variance
            bn_layer = module[1]
            num_b = bn_layer.bias.numel()  # Number of biases
            # Bias
            bn_b = torch.from_numpy(weights[ptr: ptr + num_b]).view_as(bn_layer.bias)
            bn_layer.bias.data.copy_(bn_b)
            ptr += num_b
            # Weight
            bn_w = torch.from_numpy(weights[ptr: ptr + num_b]).view_as(bn_layer.weight)
            bn_layer.weight.data.copy_(bn_w)
            ptr += num_b
            # Running Mean
            bn_rm = torch.from_numpy(weights[ptr: ptr + num_b]).view_as(bn_layer.running_mean)
            bn_layer.running_mean.data.copy_(bn_rm)
            ptr += num_b
            # Running Var
            bn_rv = torch.from_numpy(weights[ptr: ptr + num_b]).view_as(bn_layer.running_var)
            bn_layer.running_var.data.copy_(bn_rv)
            ptr += num_b
        else:
            # Load conv. bias
            num_b = conv_layer.bias.numel()
            conv_b = torch.from_numpy(weights[ptr: ptr + num_b]).view_as(conv_layer.bias)
            conv_layer.bias.data.copy_(conv_b)
            ptr += num_b
        # Load conv. weights
        num_w = conv_layer.weight.numel()
        conv_w = torch.from_numpy(weights[ptr: ptr + num_w]).view_as(conv_layer.weight)
        conv_layer.weight.data.copy_(conv_w)
        ptr += num_w

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

批量归一化:Batch Normalization层 原理+Pytorch实现 的相关文章

随机推荐

  • Hadoop学习之web查看HADOOP以及文件的上传和下载

    Hadoop学习之web查看HADOOP 1 web端查看HDFS的NameNode 浏览器输入 xff1a http hadoop1002 9870 查看HDFS上储存的数据信息 2 Web端查看YARN的ResourceManager
  • 【编译原理】实验三 NFA 确定化和 DFA 最小化

    一 实验标题 xff1a NFA确定化和 DFA 最小化 二 实验目的 xff1a 1 学习和掌握将NFA转为 DFA 的 子集构造法 2 学会编程实现等价划分法最小化DFA 三 实验内容 xff1a xff08 一 xff09 NFA确定
  • 【网络协议】openR调研

    OpenR 是 Facebook 内部设计和开发的路由协议 平台 最初于 2016 年发布 xff0c 作为所有运行于 Terragraph 上的硬件的软件基础 xff0c 提供了一个测试更快 更有效的新型路由程序的框架 xff0c 引导数
  • Linux下安装docker详细操作步骤

    Docker的几个核心概念 xff1a Docker主机 xff08 host xff09 安装了docker程序的机器Docker客户端 xff08 client xff09 连接docker主机进行操作Docker仓库 xff08 Re
  • 相对熵 KL散度 (KullbackLeibler divergence)

    这个属于香农信息论中的东西 xff0c 在 PRML 书中1 6 信息论小节中有具体说明 真正碰到应用还是在洛桑联邦理工的POM文章中 xff08 概率占用图 xff09 作者使用自己产生的估计Q来去逼近未知分布P xff0c 其中P是一个
  • Python虚拟环境——virtualenv

    林野哥推荐的虚拟环境 xff0c 这个跟Conda虚拟环境有点像 xff0c 但是和conda最大的区别就是virtualenv会创建一个单独的文件夹存放python环境 xff0c 感觉隔离程度更高 使用方法如下 xff1a 1 安装vi
  • 洛桑联邦理工 TPAMI-2008 MTMC 概率占用图POM建模过程推导 笔记

    一切都要从2019年9月的那个秋天讲起 xff0c 林野哥向我推荐了这篇洛桑联邦理工的2008年TPAMI论文 xff0c 于是一个半月的时间都花在了这上面 Multi Camera People Tracking with a Proba
  • 知识图谱笔记(小象学院课程)

    2018年寒假看小象学院课程的时候写的笔记 xff0c 一共写了10页 xff0c 记得比较乱 因为纸质笔记不容易保存 xff0c 所以把它扫成了PDF以备后用 希望大家能够指出不足和错误
  • 隐马尔可夫模型HHM重要公式推导

    我终于把HMM看完了 xff0c 这些笔记都是看的过程中自己对推导过程写的注释 xff0c 还有知识框架 原来卡尔曼和粒子滤波都是属于HMM模型里面的 笔记结构如下 xff1a 1 HMM简介 xff1a 知识体系 43 一个模型 43 两
  • MOT指标笔记《CLEAR Metrics-MOTA&MOTP》2008年·卡尔斯鲁厄大学

    搞了这么久的MOT xff0c 到头来发现最基本的MOTA和MOTP还没有搞懂 xff0c 实在有点说不过去 今天花了一上午的时间阅读2008年卡尔斯鲁厄大学的 Evaluating Multiple Object Tracking Per
  • 概率图模型-知识结构

    两周多 xff0c 终于把概率图模型这一章看完了 xff0c 由于只是看了知识框架 xff0c 很多具体细节都还不理解 内容真的是好多啊 xff0c 而且都是理论 xff0c 没有实践 希望日后用到的时候能回忆的起来这些内容吧
  • 软件工程概论-课后作业1

    需要网站系统开发需要掌握的技术 1 网页设计 xff1a Photoshop Flash max Dreamweaver 2 网站程序 xff1a Dreamweaver Visual Studio NET 会asp asp net php
  • 《强化学习》——CH2 多臂赌博机 笔记

  • 相机几何学——投影矩阵P的构成(实验报告版)

    最近在可视化WildTrack数据集 xff0c 由于要对棋盘格点进行映射和绘制 xff0c 涉及到了P矩阵的计算 现在对P的来源进行了系统的整理 xff0c 以备后忘 在最后对场地端点映射产生的问题进行了讨论 xff08 事情开始变得有意
  • 约束优化方法_2_——Frank-Wolfe方法

    Frank Wolfe方法属于约束优化中可行方向法的一种 上一篇博文对同类型的Zoutendijk可行性方法进行了介绍 xff0c 这一部分着重关注Frank Wolfe方法 Frank Wolfe方法的基本思想是 xff1a 每次迭代中使
  • 二次规划_1_——Lagrange方法

    二次规化是非线性规化中的一种特殊情形 xff0c 其目标函数是二次实函数 xff0c 约束是线性的 考试中会考到四种方法 xff0c 分别为 xff1a Lagrange方法 起作用集方法 直接消去法和广义消去法 前两种在教材上有详细描述
  • 二次规划_2_——起作用集方法

    这个算法很反人类 xff0c 迭代过程相当复杂 xff0c 最优化老师说 xff1a 明确地告诉你要考的 起作用集方法适用于消元法和Lagrange方法无法处理的不等式约束二次规化问题 其主要思想是 xff1a 以已知点为可行点 xff0c
  • 约束非线性优化:几何意义&对偶形式

    借助老师的PPT对约束非线性优化问题的几何意义 和对偶形式 进行阐述 一 几何意义 xff08 1 xff09 等式约束 考虑只有等式约束h x 的非线性优化问题 xff0c 形式为 xff1a 可视化结果如下图所示 xff0c 红色曲线为
  • 转载篇:优秀博文汇总

    1 Pytorch中堆网络语法 xff1a nn moduleList 和Sequential由来 用法和实例 写网络模型 https blog csdn net e01528 article details 84397174 2 CNN中
  • 批量归一化:Batch Normalization层 原理+Pytorch实现

    一 BN层概念明晰 BN层存在的意义 xff1a 让较深的神经网络的训练变得更加容易 BN层的工作内容 xff1a 利用小批量数据样本的均值和标准差 xff0c 不断调整神经网络中间输出 xff0c 使整个神经网络在各层的中间输出的数值更加