BN与Dropout在训练测试中的差异及其应用

需积分: 0 10 下载量 101 浏览量 更新于2024-08-05 1 收藏 620KB PDF 举报
本文主要讨论了两种在深度学习中常用的正则化技术——批量归一化(Batch Normalization, BN)和Dropout,并分析了它们在训练和测试阶段的区别。 BatchNormalization(批量归一化)是一种用于加速深度学习模型训练并提高泛化能力的技术。其主要目标是使网络各层的输入保持相对稳定的分布,从而缓解内部协变量漂移问题。在训练过程中,BN对每一批次的数据进行归一化,利用该批次数据的均值和方差。而在测试阶段,由于没有批次的概念,BN使用的是整个训练集的均值和方差,这些统计量通常通过移动平均在训练过程中计算并保存。使用全量训练集的均值和方差可能导致过拟合,因此BN在训练时采用每批数据的统计信息,增加了模型的鲁棒性。 Dropout是一种随机失活机制,主要用于减少神经元之间的依赖,防止过拟合。在训练期间,Dropout以预设的概率随机关闭(或“失活”)一部分神经元,使得模型在每次前向传播时都能看到不同的子网络。这等效于集成多个简化版的网络,提升了模型的泛化性能。然而,在测试阶段,我们不再使用Dropout,而是使用完整的模型进行预测。为了解决训练和测试阶段之间输入量级的差异,训练时会将前一层的输出除以(1-p),其中p是Dropout概率,以补偿神经元失活的影响,保持训练和测试期间输入的期望值一致。 BatchNormalization和Dropout在实践中经常结合使用,但需要注意,它们的使用策略和作用机理略有不同。BN主要通过调整输入分布来优化模型的学习过程,而Dropout则是通过随机失活来增加模型的多样性。在应用时,通常建议先进行BN,再进行Dropout,以确保Dropout操作不影响BN的归一化效果。 BN和Dropout都是为了提高深度学习模型的性能和泛化能力,它们在训练和测试阶段各有特定的实现方式,以适应不同的优化目标。理解和合理运用这两种技术对于构建高效、鲁棒的深度学习模型至关重要。

import torch import torch.nn as nn import torch.optim as optim import torchvision.datasets as datasets import torchvision.transforms as transforms # 定义超参数 batch_size = 64 learning_rate = 0.001 num_epochs = 10 # 定义数据预处理 transform = transforms.Compose([ transforms.ToTensor(), # 转换为Tensor类型 transforms.Normalize((0.1307,), (0.3081,)) # 标准化,使得均值为0,标准差为1 ]) # 加载MNIST数据集 train_dataset = datasets.MNIST(root='C:/MNIST', train=True, transform=transform, download=True) test_dataset = datasets.MNIST(root='C:/MNIST', train=False, transform=transform, download=True) train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False) # 定义CNN模型 class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1) self.bn1 = nn.BatchNorm2d(32) self.relu1 = nn.ReLU() self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1) self.bn2 = nn.BatchNorm2d(64) self.relu2 = nn.ReLU() self.pool = nn.MaxPool2d(kernel_size=2, stride=2) self.fc1 = nn.Linear(64 * 7 * 7, 128) self.relu3 = nn.ReLU() self.fc2 = nn.Linear(128, 10) def forward(self, x): out = self.conv1(x) out = self.bn1(out) out = self.relu1(out) out = self.conv2(out) out = self.bn2(out) out = self.relu2(out) out = self.pool(out) out = out.view(-1, 64 * 7 * 7) out = self.fc1(out) out = self.relu3(out) out = self.fc2(out) return out # 实例化模型并定义损失函数和优化器 model = CNN() criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=learning_rate) # 训练模型 total_step = len(train_loader) for epoch in range(num_epochs): for i, (images, labels) in enumerate(train_loader): # 前向传播 outputs = model(images) loss = criterion(outputs, labels) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() # 每100个batch打印一次训练信息 if (i+1) % 100 == 0: print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' .format(epoch+1, num_epochs, i+1, total_step, loss.item())) # 测试模型 model.eval() # 进入测试模式,关闭Dropout和BatchNormalization层 with torch.no_grad(): correct = 0 total = 0 for images, labels in test_loader: outputs = model(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))运行一下此代码

2023-06-01 上传