批量規(guī)范化(Batch Normalization)是深度學(xué)習(xí)中一種常用的技術(shù),用于加速訓(xùn)練過程并提高模型的穩(wěn)定性和泛化能力。以下是PyTorch中批量規(guī)范化的一些關(guān)鍵知識點:
1.nn.BatchNorm1d 和 nn.BatchNorm2d:
2.PyTorch提供了nn.BatchNorm1d用于在全連接層后應(yīng)用批量規(guī)范化,以及nn.BatchNorm2d用于在卷積層后應(yīng)用批量規(guī)范化。
3.通過這兩個模塊,可以輕松在模型中的不同層應(yīng)用批量規(guī)范化。
4.訓(xùn)練和測試模式:
5.批量規(guī)范化層在訓(xùn)練和測試階段的計算方式不同。
6.在訓(xùn)練時,它使用當(dāng)前批次的均值和方差進(jìn)行歸一化。
7.在測試時,通常使用保存的移動平均值和方差進(jìn)行歸一化。
8.model.train() 和 model.eval() 方法:
9.在使用批量規(guī)范化的模型中,需要在訓(xùn)練和測試階段切換模型的狀態(tài),使用model.train()將模型切換到訓(xùn)練模式,而使用model.eval()切換到測試模式。
10.批量規(guī)范化的計算過程:
11.對于每個輸入特征,批量規(guī)范化執(zhí)行以下步驟:
12.計算當(dāng)前批次的均值和方差。
13.使用批次的均值和方差對輸入進(jìn)行標(biāo)準(zhǔn)化。
14.通過縮放和平移操作,將標(biāo)準(zhǔn)化后的值映射回新的分布,從而引入可學(xué)習(xí)的參數(shù)。
15.批量規(guī)范化的參數(shù):
16.批量規(guī)范化引入了可學(xué)習(xí)的參數(shù),包括縮放參數(shù)(gamma)和平移參數(shù)(beta)。
17.這些參數(shù)允許模型學(xué)習(xí)適應(yīng)數(shù)據(jù)的最佳標(biāo)準(zhǔn)化。
18.移動平均:
19.在測試時,批量規(guī)范化層通常使用移動平均來估計整個訓(xùn)練數(shù)據(jù)集的均值和方差。
20.這有助于提高模型在測試集上的泛化性能。
21.批量規(guī)范化的位置:
22.批量規(guī)范化可以在模型的不同層中使用,包括全連接層和卷積層。
23.它通常在激活函數(shù)之前應(yīng)用,即在全連接或卷積操作之后,激活函數(shù)之前。
24.對學(xué)習(xí)率和權(quán)重初始化的影響:
25.批量規(guī)范化有助于減小對學(xué)習(xí)率和權(quán)重初始化的敏感性,使得在更大范圍內(nèi)選擇合適的學(xué)習(xí)率和初始化值更為容易。文章來源:http://www.zghlxwxcb.cn/news/detail-791946.html
這些知識點涵蓋了在PyTorch中使用批量規(guī)范化時的一些關(guān)鍵概念和實踐。使用批量規(guī)范化可以顯著改善訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)的效果,特別是在深層網(wǎng)絡(luò)中。文章來源地址http://www.zghlxwxcb.cn/news/detail-791946.html
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import os
# 設(shè)置環(huán)境變量以避免 OpenMP 問題
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
class NeuralNetWithBatchNorm(nn.Module):
def __init__(self, use_batch_norm, input_size=784, hidden_dim=256, output_size=10):
super(NeuralNetWithBatchNorm, self).__init__()
self.input_size = input_size
self.hidden_dim = hidden_dim
self.output_size = output_size
self.use_batch_norm = use_batch_norm
# 第一個全連接層。如果使用批量歸一化,則在其后添加批量歸一化層
self.fc1 = nn.Linear(input_size, hidden_dim, bias=not use_batch_norm)
if use_batch_norm:
self.batch_norm1 = nn.BatchNorm1d(hidden_dim)
# 第二層全連接層。與 fc1類似,如果 use_batch_norm是True ,則添加批處理歸一化層 ()
self.fc2 = nn.Linear(hidden_dim, hidden_dim, bias=not use_batch_norm)
if use_batch_norm:
self.batch_norm2 = nn.BatchNorm1d(hidden_dim)
# 最終的全連接層。
self.fc3 = nn.Linear(hidden_dim, output_size)
def forward(self, x):
# 將輸入調(diào)整為第一維的大小
x = x.view(-1, 28 * 28)
# 按順序應(yīng)用的全連接層。
x = self.fc1(x)
# 如果 use_batch_norm是True ,則在全連接層之后應(yīng)用批量歸一化。
if self.use_batch_norm:
x = self.batch_norm1(x)
# 在全連接層之間應(yīng)用整流線性單元 (ReLU) 激活功能。
x = F.relu(x)
x = self.fc2(x)
if self.use_batch_norm:
x = self.batch_norm2(x)
x = self.fc3(x)
return x
# model:要訓(xùn)練的神經(jīng)網(wǎng)絡(luò)模型。
# train_loader:訓(xùn)練數(shù)據(jù)集的 PyTorch 數(shù)據(jù)加載器。
# n_epochs:訓(xùn)練周期數(shù)(默認(rèn)設(shè)置為 10)
def train(model, train_loader, n_epochs=10):
# 將 epoch 的數(shù)量分配給局部變量,并創(chuàng)建一個空列表來存儲每個 epoch 期間的訓(xùn)練損失。
n_epochs = n_epochs
losses = []
# nn.CrossEntropyLoss():這是交叉熵?fù)p失,通常用于分類問題。
# optim.SGD():隨機(jī)梯度下降優(yōu)化器的使用學(xué)習(xí)率為 0.01。它優(yōu)化了神經(jīng)網(wǎng)絡(luò)的參數(shù)()。
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 這會將模型設(shè)置為訓(xùn)練模式,如果模型包含在訓(xùn)練和評估期間表現(xiàn)不同的輟學(xué)或批量歸一化等層,則這是必需的。
model.train()
# 該函數(shù)遍歷每個紀(jì)元。
for epoch in range(1, n_epochs + 1):
train_loss = 0.0
batch_count = 0
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
train_loss += loss.item()
batch_count += 1
losses.append(train_loss / batch_count)
print('Epoch:{}\t Training Loss:{:6f}'.format(epoch, train_loss / batch_count))
# train_loss:當(dāng)前時期訓(xùn)練損失的累加器。
# batch_count:處理的批次數(shù)的計數(shù)器。
# optimizer.zero_grad():清除在上一次迭代中計算的梯度。
# output = model(data):前向通過模型。
# loss = criterion(output, target):根據(jù)模型的輸出和目標(biāo)標(biāo)簽計算損失。
# loss.backward():向后傳遞以計算參數(shù)的梯度。
# optimizer.step():使用優(yōu)化器更新模型參數(shù)。
# train_loss += loss.item():累積當(dāng)前批次的訓(xùn)練損失。
# batch_count += 1:遞增批次計數(shù)。
# losses.append(train_loss / batch_count):記錄當(dāng)前 epoch 的平均訓(xùn)練損失。
# print(...):顯示紀(jì)元編號和相應(yīng)的訓(xùn)練損失。
return losses
# num_workers:用于數(shù)據(jù)加載的子進(jìn)程數(shù)。此處設(shè)置為 0,表示數(shù)據(jù)加載將在主進(jìn)程中進(jìn)行。
# batch_size:每批樣品數(shù)。
# transform:的實例,用于將 PIL 圖像或 numpy 數(shù)組轉(zhuǎn)換為火炬張量。transforms.ToTensor()
num_workers = 0
batch_size = 64
transform = transforms.ToTensor()
# datasets.MNIST:加載 MNIST 數(shù)據(jù)集。
# root='data':指定存儲數(shù)據(jù)集的目錄。
# train=True:表示這是數(shù)據(jù)集的訓(xùn)練拆分。
# download=True:下載數(shù)據(jù)集(如果尚不存在)。
# transform=transform:將指定的轉(zhuǎn)換(在本例中為)應(yīng)用于數(shù)據(jù)。
train_data = datasets.MNIST(root='data', train=True, download=True, transform=transform)
# torch.utils.data.DataLoader:創(chuàng)建用于遍歷數(shù)據(jù)集的數(shù)據(jù)加載器。
# train_data:要加載的數(shù)據(jù)集。
# batch_size:每批樣品數(shù)。
# num_workers:用于數(shù)據(jù)加載的子進(jìn)程數(shù)。
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=num_workers)
# NeuralNetWithBatchNorm:假定存在一個名為 的神經(jīng)網(wǎng)絡(luò)類。
# use_batch_norm=True:表示具有批量歸一化的網(wǎng)絡(luò)應(yīng)使用批量歸一化層進(jìn)行實例化。
# use_batch_norm=False:表示沒有批量歸一化的網(wǎng)絡(luò)應(yīng)該在沒有批量歸一化層的情況下實例化。
net_batchnorm = NeuralNetWithBatchNorm(use_batch_norm=True)
net_no_norm = NeuralNetWithBatchNorm(use_batch_norm=False)
# 打印實例
print(net_batchnorm)
print(net_no_norm)
print()
# Train the models
losses_batchnorm = train(net_batchnorm, train_loader)
losses_no_norm = train(net_no_norm, train_loader)
# Plot the training losses
fig, ax = plt.subplots(figsize=(12, 8))
plt.plot(losses_batchnorm, label='Using batchnorm', alpha=0.5)
plt.plot(losses_no_norm, label='No norm', alpha=0.5)
plt.title("Training Losses")
plt.legend()
plt.show()
# 測試功能
def test(model, train_loader, train=True):
# 初始化:
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
test_loss = 0.0
# 將模型設(shè)置為訓(xùn)練或評估模式
# 只是為了看到行為上的差異
if train:
model.train()
else:
model.eval()
# 損失標(biāo)準(zhǔn)
criterion = nn.CrossEntropyLoss()
for batch_idx, (data, target) in enumerate(train_loader):
batch_size = data.size(0)
output = model(data)
loss = criterion(output, target)
test_loss += loss.item() * batch_size
_, pred = torch.max(output, 1)
correct = np.squeeze(pred.eq(target.data.view_as(pred)))
for i in range(batch_size):
label = target.data[i]
class_correct[label] += correct[i].item()
class_total[label] += 1
# 打印測試損失
print('Test Loss: {:.6f}\n'.format(test_loss / len(train_loader.dataset)))
# 每個類別的打印精度
for i in range(10):
if class_total[i] > 0:
print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (
str(i), 100 * class_correct[i] / class_total[i],
np.sum(class_correct[i]), np.sum(class_total[i])))
else:
print('Test Accuracy of %5s: N/A (no training examples)' % (i))
# 打印整體精度
print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (
100. * np.sum(class_correct) / np.sum(class_total),
np.sum(class_correct), np.sum(class_total)))
# 測試模型
test(net_batchnorm, train_loader, train=True)
test(net_batchnorm, train_loader, train=False)
test(net_no_norm, train_loader, train=False)
到了這里,關(guān)于PyTorch 中的批量規(guī)范化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!