首页 > 其他分享 >深度学习——批量归一化处理

深度学习——批量归一化处理

时间:2024-07-22 18:28:34浏览次数:19  
标签:批量 nn 方差 self 归一化 moving 深度 var mean

1.为什么要进行归一化处理

1.对于我们输入而言,标准化输入是一项重要的步骤,例如预测房间时,我们让特征值方差为1,均值为0,可以使我们的参数量级做到统一

2.对于典型的多层感知机而言,有些层输出的范围可能与输入的范围存在过大的区别,导致我们的模型收敛速度过慢

3.越深的模型,越容易过拟合·,就越需要正则化

2.归一化操作

具体流程:在每次训练迭代中,我们首先规范化输入,即通过减去其均值并除以其标准差,其中两者均基于当前小批量处理。接下来,我们应用比例系数和比 例偏移。 简单来说就是先将数据每个批次对应的特征归一化到均值为0,方差为1的区间,然后乘以一个可学习的y和加上一个偏执b

特别的当批量大小为1时,我们学习不到任何东西,因为减去均值后,每个特征都为0 ,所以需要使用足够大的批量,批量规范化才是稳定的

我们的均值和方差是通过以下方法求出的

 对于多层感知机而言,均值和方差是对一个批次中相同特征求(64,32)->(1,32),而对于卷积而言,是对于通道数去求,就相当于(3,3,224,224)批量为3的数据,变为(1,3,1,1)求每个通道的均值

特:我们在方差上加入了一个小的噪音,可以有效解决计算时除以0的问题,并且加入噪音也有利于我们去正则化

批量规范化层在”训练模式“和“预测模式”中的功能不同。在训练过程中,我们无法得知使用整个数据集来估计平均值和方差,所以只能根据每个小批 次的平均值和方差不断训练模型。而在预测模式下,可以根据整个数据集精确计算批量规范化所需的平均值 和方差。

 从零实现

引入

import torch
from torch import nn
from d2l import torch as d2l

对于归一化块的实现

def batch_norm(X,gamma,beta,moving_mean,moving_var,eps,momentum):#eps防止除以0
    #通过is_grad_enabled判断是推理模式还是训练模式
    if not torch.is_grad_enabled():
        X_hat=(X-moving_mean)/torch.sqrt(moving_var+eps)
    else:
        assert len(X.shape)in(2,4)
        if len(X.shape)==2:
            #计算全连接层情况
            mean=X.mean(dim=0)
            var=((X-mean)**2).mean(dim=0)
        else:
            #计算二维卷积层的情况
            mean=X.mean(dim=(0,2,3),keepdim=True)#对通道做做平均  相当于一个一个取平均0 2 3维
            var=((X-mean)**2).mean(dim=(0,2,3),keepdim=True)#触发广播机制
        #训练模式下,采用当前均值和方差做标准化
        X_hat=(X-mean)/torch.sqrt(var+eps)
        #更新移动的均值方差
        moving_mean=momentum*moving_mean+(1-momentum)*mean
        moving_var=momentum*moving_var+(1-momentum)*var
    Y=gamma*X_hat+beta#注意这里用的是点乘
    return Y,moving_mean.data,moving_var.data

 注意:我们在理想情况下希望的均值和方差是整个样本的,而不是批次,但在训练过程中我们是用批次的的均值和方差估算整体的,同时通过移动平均估算整个训练数据集的样 本均值和方差

所以在训练时用的是批次的均值和方差,而预测时用的是估算整个训练数据集的样 本均值和方差

归一化层的实现

class BatchNorm(nn.Module):
    def __init__(self,num_features,num_dims):
        super().__init__()
        if num_dims==2:
            shape=(1,num_features)
        else:
            shape=(1,num_features,1,1)
        #申请可学习的参数
        self.gamma = nn.Parameter(torch.ones(shape))
        self.beta = nn.Parameter(torch.zeros(shape))
        #定义移动均值为0,方差为1
        self.moving_mean = torch.zeros(shape)
        self.moving_var = torch.ones(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)
            #保存更新过的参数
        Y, self.moving_mean, self.moving_var = batch_norm(
            X, self.gamma, self.beta, self.moving_mean,
            self.moving_var, eps=1e-5, momentum=0.9)
        return Y

num_features是特征的数量,num_dims是输入的维度,通过这两个去计算我们参数的形状

训练参数设置及训练

lr, num_epochs, batch_size = 1.0, 10, 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
d2l.plt.show()
torch.save(net.state_dict(),"规范化")

结果

 批量归一化简介实现

其余的不变

net = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5), nn.BatchNorm2d(6), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5), nn.BatchNorm2d(16), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),
nn.Linear(256, 120), nn.BatchNorm1d(120), nn.Sigmoid(),
nn.Linear(120, 84), nn.BatchNorm1d(84), nn.Sigmoid(),
nn.Linear(84, 10))

nn.batchnorm2d只接受特征数量,自动识别维度

标签:批量,nn,方差,self,归一化,moving,深度,var,mean
From: https://blog.csdn.net/2301_79972308/article/details/140612761

相关文章

  • mybatis使用foreach批量插入
    创建表createtablepublic."match"(match_datedatenotnull,match_namecharactervarying(20)notnull,match_seasoncharactervarying(10)notnull,match_roundnumeric(2)notnull,home_teamcharactervarying(30)notnull,away_teamcharact......
  • 如何批量上传到Remini?
    因此,我必须使用Android上的Remini应用程序来增强上千张不同的图像。我尝试手动处理这些图像,但每张图像都花费了我30秒的时间和大量的精力。问题是我总是需要从图库中选择不同的图像,然后等到它得到增强,然后我可以将其保存到我的图库中。遗憾的是,Remini不允许您批量上传......
  • 用SqlBulkCopy批量插入数据 遇到的错误
    原文链接:https://www.cnblogs.com/wz327/archive/2011/07/05/2098356.html错误一:来自数据源的String类型的给定值不能转换为指定目标列的类型nvarchar。还有其他的错误如:AddTime不能为DBNull(这个应该是目标表中AddTime要求不许为null) 可能的原因有两种可能是有"'"(单引......
  • 使用 Open3D 点云到 RGB 图像转换中的颜色不匹配和深度不一致
    我正在使用Open3D将点云数据转换为RGB图像。但是,我遇到了输出图像中的颜色与输入点云中的颜色不匹配的问题。此外,本应位于背景的点却出现在前景中。这是我的代码的相关部分:importnumpyasnpimportcv2classProjector:def__init__(self,cloud)->None:......
  • 深度学习笔记
    相关学习资料https://tangshusen.me/Dive-into-DL-PyTorch/#/http://zh.d2l.ai/https://discuss.gluon.ai/c/lecture?order=views初始环境配置#下载安装脚本:https://conda.io/en/latest/miniconda.html#安装miniconda#macosshMiniconda3-py39_4.12.0-MacOSX-x86_......
  • 动手学深度学习(线性神经网络)
    看这一节前最好先移动至--动手学深度学习(预备知识),把基础知识打牢,使后续理解代码和原理更加容易因为这里是第三章的内容了,所以笔者的目录就从3开始咯。目录3.线性神经网络3.1线性回归3.11线性回归的基本元素3.12损失函数3.13解析解3.14随机梯度下降3.15矢量化加速3......
  • 保姆教程深度学习(多层感知机)一份足矣
    多层感知机一.隐藏层和激活函数1.为什么需要隐藏层?前面几篇博客我们通过基础知识,学习了如何处理数据,如何将输出转换为有效的概率分布,并应用适当的损失函数,根据模型参数最小化损失。但是记不记得当时我们算出来的数据都是线性的,我们把一张图片28*28=784的每一个像素视为一......
  • linux-批量修改文件内容
    1.批量修改文件内容$find.-typef-execsed-i's/oldname/newname/g'{}+#此命令含义:在当前目录及其所有子目录中查找所有文件,并对这些文件执行sed命令,将文件内容中的所有oldname字符串替换为newname。#find.:从当前目录(.)开始查找文件。#typef:指定查找的类型为文......
  • 深度学习代码改进
     在线个人接代码改进,代跑通,预测模型,模型优化,增加模块,python代做,预测,微调,融合,强化学习,深度学习,机器学习程序代写,环境调试,代码调通,模型优化,模型修改,时间序列,机器学习数据处理等开发工程项目主攻:Pytorch,Tensorflow,Yolo,Unet,DNN,CNN,GAN,Transformer,matlab训练模型,优化......
  • 具有未定义嵌套列表深度的嵌套列表的Python注释类型
    [[1,2,3],3,[2,4],5]的类型是list[list[int]|int]但是,如果嵌套列表具有未定义的深度,例如[[[1,2]],2,[1,[3,[3]]]],3,[2,[2]]],那么它会具有什么类型?可以使用递归类型提示来表示任意深度嵌套的列表:fromtypingimportList,Union......