批量归一化

37 篇文章 1 订阅
27 篇文章 1 订阅

引言

在深度学习中,批量归一化(Batch Normalization, BN)是一种非常重要的技术,它可以加速神经网络的训练,提高模型的泛化性能。本文将详细介绍批量归一化的原理、方法和实现过程,并给出PyTorch代码示例。

原理

在深度神经网络中,输入数据经过多层非线性变换后,分布会逐渐发生变化,导致每一层的输入分布都不同,这会影响网络的训练效果。批量归一化通过对每一层的输入进行归一化处理,使得每一层的输入分布相对稳定,从而加速网络的收敛速度,提高模型的泛化性能。

方法

批量归一化的方法如下:

  1. 对每个mini-batch的数据,计算其均值和方差;
  2. 对每个输入数据进行归一化处理;
  3. 对归一化后的数据进行线性变换,得到新的特征值;
  4. 对新的特征值进行缩放和平移,得到最终的输出。

具体来说,对于一个mini-batch的数据 B = { x 1 , x 2 , . . . , x m } B=\{x_1,x_2,...,x_m\} B={x1,x2,...,xm},其中 x i x_i xi表示第 i i i个输入数据,其均值和方差分别为:

μ B = 1 m ∑ i = 1 m x i \mu_B = \frac{1}{m}\sum_{i=1}^m x_i μB=m1i=1mxi

σ B 2 = 1 m ∑ i = 1 m ( x i − μ B ) 2 \sigma_B^2 = \frac{1}{m}\sum_{i=1}^m (x_i-\mu_B)^2 σB2=m1i=1m(xiμB)2

对每个输入数据进行归一化处理:

x i ^ = x i − μ B σ B 2 + ϵ \hat{x_i} = \frac{x_i - \mu_B}{\sqrt{\sigma_B^2+\epsilon}} xi^=σB2+ϵ xiμB

其中 ϵ \epsilon ϵ是一个较小的常数,避免分母为0。

对归一化后的数据进行线性变换:

y i = γ x i ^ + β y_i = \gamma\hat{x_i} + \beta yi=γxi^+β

其中 γ \gamma γ β \beta β是可学习的参数,用于缩放和平移数据分布。

实现

在PyTorch中,可以使用nn.BatchNorm2d来实现批量归一化。下面是一个简单的示例:

import torch
import torch.nn as nn

# 定义一个简单的网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.bn1 = nn.BatchNorm2d(6)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.bn2 = nn.BatchNorm2d(16)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = nn.functional.relu(x)
        x = nn.functional.max_pool2d(x, 2)
        x = self.conv2(x)
        x = self.bn2(x)
        x = nn.functional.relu(x)
        x = nn.functional.max_pool2d(x, 2)
        x = x.view(-1, 16 * 5 * 5)
        x = self.fc1(x)
        x = nn.functional.relu(x)
        x = self.fc2(x)
        x = nn.functional.relu(x)
        x = self.fc3(x)
        return x

# 定义一个简单的训练过程
def train(net, trainloader, loss_func, optimizer, device):
    net.train()
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)

        optimizer.zero_grad()

        outputs = net(inputs)
        loss = loss_func(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()
        if i % 2000 == 1999:
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

# 加载数据集并进行训练
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=True, transform=transforms.ToTensor())
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
                                          shuffle=True, num_workers=2)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = Net().to(device)
loss_func = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

for epoch in range(10):
    train(net, trainloader, loss_func, optimizer, device)

结构图

使用Mermaid代码可以绘制批量归一化的结构图,如下所示:

Input
Normalization
Linear Transform
Scaling and Shifting
Output

其中,输入数据经过归一化、线性变换、缩放和平移后,得到最终的输出。

总结

批量归一化是一种非常重要的技术,它可以加速神经网络的训练,提高模型的泛化性能。本文介绍了批量归一化的原理、方法和实现过程,并给出了PyTorch代码示例。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值