目錄
一.概念介紹
1.1神經(jīng)網(wǎng)絡(luò)核心組件
1.2神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)示意圖
1.3使用pytorch構(gòu)建神經(jīng)網(wǎng)絡(luò)的主要工具
二、實現(xiàn)手寫數(shù)字識別
2.1環(huán)境
2.2主要步驟
2.3神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
2.4準備數(shù)據(jù)
2.4.1導(dǎo)入模塊
2.4.2定義一些超參數(shù)
2.4.3下載數(shù)據(jù)并對數(shù)據(jù)進行預(yù)處理
2.4.4可視化數(shù)據(jù)集中部分元素
?2.4.5構(gòu)建模型和實例化神經(jīng)網(wǎng)絡(luò)
2.4.6訓(xùn)練模型
2.4.7可視化損失函數(shù)
2.4.7.1?train? loss?
?2.4.7.2?test?loss
一.概念介紹
????????神經(jīng)網(wǎng)絡(luò)是一種計算模型,它模擬了人類神經(jīng)系統(tǒng)的工作方式,由大量的神經(jīng)元和它們之間的連接組成。每個神經(jīng)元接收一些輸入信息,并對這些信息進行處理,然后將結(jié)果傳遞給其他神經(jīng)元。這些神經(jīng)元之間的連接具有不同的權(quán)重,這些權(quán)重可以根據(jù)神經(jīng)網(wǎng)絡(luò)的訓(xùn)練數(shù)據(jù)進行調(diào)整。通過調(diào)整權(quán)重,神經(jīng)網(wǎng)絡(luò)可以對輸入數(shù)據(jù)進行分類、回歸、聚類等任務(wù)。
????????通俗來講,神經(jīng)網(wǎng)絡(luò)就是設(shè)置一堆參數(shù),初始化這堆參數(shù),然后通過求導(dǎo),知道這些參數(shù)對結(jié)果的影響,然后調(diào)整這些參數(shù)的大小。直到參數(shù)大小可以接近完美地擬合實際結(jié)果。神經(jīng)網(wǎng)絡(luò)有兩個部分:正向傳播和反向傳播。正向傳播是求值,反向傳播是求出參數(shù)對結(jié)果的影響,從而調(diào)整參數(shù)。所以,神經(jīng)網(wǎng)絡(luò):正向傳播->反向傳播->正向傳播->反向傳播……? ? ?
????????比如我們要預(yù)測一個圖像是不是貓。如果是貓,它的結(jié)果就是1,如果不是貓,它的結(jié)果就是0.我們現(xiàn)在有一堆圖片,有的是貓,有的不是貓,所以它對應(yīng)的標簽(這個是y)是:0 1 1 0 1。而我們的預(yù)測結(jié)果可能是對的,也可能是錯的,假設(shè)我們的預(yù)測結(jié)果是:0 0 1 1 0.我們有3個預(yù)測對了,有2個預(yù)測錯了。那么我們的損失值是2/5。當然這么搞的話太“粗糙”了,實際上我們會有一個函數(shù)來定義損失值是什么。而且我們的預(yù)測結(jié)果也不是一個確鑿的數(shù)字,而是一個概率:比如我們預(yù)測第3張圖片是貓的概率是0.8,那么我們的預(yù)測結(jié)果是0.8.總之,定義了損失值(這個損失值記為J)以后,我們要讓這個損失值盡可能地小。
參考:什么是神經(jīng)網(wǎng)絡(luò)? - 緋紅之刃的回答 - 知乎?
1.1神經(jīng)網(wǎng)絡(luò)核心組件
? ? ? ? 神經(jīng)網(wǎng)絡(luò)看上去挺復(fù)雜,節(jié)點多,層多,參數(shù)多,但其結(jié)構(gòu)都是類似的,核心部分和組件都是相通的,確定完這些核心組件,這個神經(jīng)網(wǎng)絡(luò)也就基本確定了。
核心組件包括:
(1)層:神經(jīng)網(wǎng)絡(luò)的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)是層,層是一個數(shù)據(jù)處理模塊,它接受一個或多個張量作為輸入,并輸出一個或多個張量,由一組可調(diào)整參數(shù)描述。
(2)模型:模型是由多個層組成的網(wǎng)絡(luò),用于對輸入數(shù)據(jù)進行分類、回歸、聚類等任務(wù)。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-628627.html
(3)損失函數(shù):參數(shù)學(xué)習(xí)的目標函數(shù),通過最小化損失函數(shù)來學(xué)習(xí)各種參數(shù)。損失函數(shù)是衡量模型輸出結(jié)果與真實標簽之間的差異的函數(shù),目標是最小化損失函數(shù),提高模型性能。
(4)優(yōu)化器:使損失函數(shù)的值最小化。根據(jù)損失函數(shù)的梯度更新神經(jīng)網(wǎng)絡(luò)中的權(quán)重和偏置,以使損失函數(shù)的值最小化,提高模型性能和穩(wěn)定性。
1.2神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)示意圖
?描述:多個層鏈接在一起構(gòu)成一個模型或網(wǎng)絡(luò),輸入數(shù)據(jù)通過這個模型轉(zhuǎn)換為預(yù)測值,然后損失函數(shù)把預(yù)測值與真實值進行比較,得到損失值(損失值可以是距離、概率值等),該損失值用于衡量預(yù)測值與目標結(jié)果的匹配或相似程度,優(yōu)化器利用損失值更新權(quán)重參數(shù),從而使損失值越來越小。這是一個循環(huán)過程,損失值達到一個閥值或循環(huán)次數(shù)到達指定次數(shù),循環(huán)結(jié)束。
1.3使用pytorch構(gòu)建神經(jīng)網(wǎng)絡(luò)的主要工具
?參考:第3章 Pytorch神經(jīng)網(wǎng)絡(luò)工具箱 | Python技術(shù)交流與分享
在PyTorch中,構(gòu)建神經(jīng)網(wǎng)絡(luò)主要使用以下工具:
-
torch.nn模塊:提供了構(gòu)建神經(jīng)網(wǎng)絡(luò)所需的各種層和模塊,如全連接層、卷積層、池化層、循環(huán)神經(jīng)網(wǎng)絡(luò)等。
-
torch.nn.functional模塊:提供了一些常用的激活函數(shù)和損失函數(shù),如ReLU、Sigmoid、CrossEntropyLoss等。
-
torch.optim模塊:提供了各種優(yōu)化器,如SGD、Adam、RMSprop等,用于更新神經(jīng)網(wǎng)絡(luò)中的權(quán)重和偏置。
-
torch.utils.data模塊:提供了處理數(shù)據(jù)集的工具,如Dataset、DataLoader等,可以方便地處理數(shù)據(jù)集、進行批量訓(xùn)練等操作。
這些工具之間的相互關(guān)系如下:
-
使用torch.nn模塊構(gòu)建神經(jīng)網(wǎng)絡(luò)的各個層和模塊。
-
使用torch.nn.functional模塊中的激活函數(shù)和損失函數(shù)對神經(jīng)網(wǎng)絡(luò)進行非線性變換和優(yōu)化。
-
使用torch.optim模塊中的優(yōu)化器對神經(jīng)網(wǎng)絡(luò)中的權(quán)重和偏置進行更新,以最小化損失函數(shù)。
-
使用torch.utils.data模塊中的數(shù)據(jù)處理工具對數(shù)據(jù)集進行處理,方便地進行批量訓(xùn)練和數(shù)據(jù)預(yù)處理。
二、實現(xiàn)手寫數(shù)字識別
2.1環(huán)境
????????實例環(huán)境使用Pytorch1.0+,GPU或CPU,源數(shù)據(jù)集為MNIST。
2.2主要步驟
(1)利用Pytorch內(nèi)置函數(shù)mnist下載數(shù)據(jù)
(2)利用torchvision對數(shù)據(jù)進行預(yù)處理,調(diào)用torch.utils建立一個數(shù)據(jù)迭代器
(3)可視化源數(shù)據(jù)
(4)利用nn工具箱構(gòu)建神經(jīng)網(wǎng)絡(luò)模型
(5)實例化模型,并定義損失函數(shù)及優(yōu)化器
(6)訓(xùn)練模型
(7)可視化結(jié)果
2.3神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
實驗中使用兩個隱含層,每層激活函數(shù)為Relu,最后使用torch.max(out,1)找出張量out最大值對應(yīng)索引作為預(yù)測值。
2.4準備數(shù)據(jù)
2.4.1導(dǎo)入模塊
import numpy as np
import torch
# 導(dǎo)入 pytorch 內(nèi)置的 mnist 數(shù)據(jù)
from torchvision.datasets import mnist
#導(dǎo)入預(yù)處理模塊
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
#導(dǎo)入nn及優(yōu)化器
import torch.nn.functional as F
import torch.optim as optim
from torch import nn
2.4.2定義一些超參數(shù)
# 定義訓(xùn)練和測試時的批處理大小
train_batch_size = 64
test_batch_size = 128
# 定義學(xué)習(xí)率和迭代次數(shù)
learning_rate = 0.01
num_epoches = 20
# 定義優(yōu)化器的超參數(shù)
lr = 0.01
momentum = 0.5
#動量優(yōu)化器通過引入動量參數(shù)(Momentum),在更新參數(shù)時考慮之前的梯度信息,可以使得參數(shù)更新方向更加穩(wěn)定,同時加速梯度下降的收斂速度。動量參數(shù)通常設(shè)置在0.5到0.9之間,可以根據(jù)具體情況進行調(diào)整。
2.4.3下載數(shù)據(jù)并對數(shù)據(jù)進行預(yù)處理
#定義預(yù)處理函數(shù),這些預(yù)處理依次放在Compose函數(shù)中。
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize([0.5], [0.5])])
#下載數(shù)據(jù),并對數(shù)據(jù)進行預(yù)處理
train_dataset = mnist.MNIST('./data', train=True, transform=transform, download=True)
test_dataset = mnist.MNIST('./data', train=False, transform=transform)
#dataloader是一個可迭代對象,可以使用迭代器一樣使用。
train_loader = DataLoader(train_dataset, batch_size=train_batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=test_batch_size, shuffle=False)
注:
①transforms.Compose可以把一些轉(zhuǎn)換函數(shù)組合在一起;
②Normalize([0.5], [0.5])對張量進行歸一化,這里兩個0.5分別表示對張量進行歸一化的全局平均值和方差。因圖像是灰色的只有一個通道,如果有多個通道,需要有多個數(shù)字,如三個通道,應(yīng)該是Normalize([m1,m2,m3], [n1,n2,n3])
③download參數(shù)控制是否需要下載,如果./data目錄下已有MNIST,可選擇False。
④用DataLoader得到生成器,這可節(jié)省內(nèi)存。
2.4.4可視化數(shù)據(jù)集中部分元素
# 導(dǎo)入matplotlib.pyplot庫,并設(shè)置inline模式
import matplotlib.pyplot as plt
%matplotlib inline
# 枚舉數(shù)據(jù)加載器中的一批數(shù)據(jù)
examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
# 創(chuàng)建一個圖像對象
fig = plt.figure()
# 顯示前6個圖像和對應(yīng)的標簽
for i in range(6):
plt.subplot(2,3,i+1) # 將圖像分成2行3列,當前位置為第i+1個
plt.tight_layout() # 自動調(diào)整子圖之間的間距
plt.imshow(example_data[i][0], cmap='gray', interpolation='none') # 顯示圖像
plt.title("Ground Truth: {}".format(example_targets[i])) # 顯示標簽
plt.xticks([]) # 隱藏x軸刻度
plt.yticks([]) # 隱藏y軸刻度
注:
-
導(dǎo)入matplotlib.pyplot庫,并設(shè)置inline模式,以在Jupyter Notebook中顯示圖像。
-
枚舉數(shù)據(jù)加載器中的一批數(shù)據(jù),其中test_loader是一個測試數(shù)據(jù)集加載器。
-
創(chuàng)建一個圖像對象,用于顯示圖像和標簽。
-
顯示前6個圖像和對應(yīng)的標簽,其中plt.subplot()用于將圖像分成2行3列,plt.tight_layout()用于自動調(diào)整子圖之間的間距,plt.imshow()用于顯示圖像,plt.title()用于顯示標簽,plt.xticks()和plt.yticks()用于隱藏x軸和y軸的刻度。
?2.4.5構(gòu)建模型和實例化神經(jīng)網(wǎng)絡(luò)
class Net(nn.Module):
"""
使用sequential構(gòu)建網(wǎng)絡(luò),Sequential()函數(shù)的功能是將網(wǎng)絡(luò)的層組合到一起
"""
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super(Net, self).__init__()
self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1))
self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2))
self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim))
def forward(self, x):
x = F.relu(self.layer1(x))
x = F.relu(self.layer2(x))
x = self.layer3(x)
return x
#檢測是否有可用的GPU,有則使用,否則使用CPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#實例化網(wǎng)絡(luò)
model = Net(28 * 28, 300, 100, 10)
model.to(device)
# 定義損失函數(shù)和優(yōu)化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=momentum)
2.4.6訓(xùn)練模型
# 開始訓(xùn)練
losses = []
acces = []
eval_losses = []
eval_acces = []
for epoch in range(num_epoches):
train_loss = 0
train_acc = 0
model.train()
#動態(tài)修改參數(shù)學(xué)習(xí)率
if epoch%5==0:
optimizer.param_groups[0]['lr']*=0.1
for img, label in train_loader:
img=img.to(device)
label = label.to(device)
img = img.view(img.size(0), -1)
# 前向傳播
out = model(img)
loss = criterion(out, label)
# 反向傳播
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 記錄誤差
train_loss += loss.item()
# 計算分類的準確率
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
train_acc += acc
losses.append(train_loss / len(train_loader))
acces.append(train_acc / len(train_loader))
# 在測試集上檢驗效果
eval_loss = 0
eval_acc = 0
# 將模型改為預(yù)測模式
model.eval()
for img, label in test_loader:
img=img.to(device)
label = label.to(device)
img = img.view(img.size(0), -1)
out = model(img)
loss = criterion(out, label)
# 記錄誤差
eval_loss += loss.item()
# 記錄準確率
_, pred = out.max(1)
num_correct = (pred == label).sum().item()
acc = num_correct / img.shape[0]
eval_acc += acc
eval_losses.append(eval_loss / len(test_loader))
eval_acces.append(eval_acc / len(test_loader))
print('epoch: {}, Train Loss: {:.4f}, Train Acc: {:.4f}, Test Loss: {:.4f}, Test Acc: {:.4f}'
.format(epoch, train_loss / len(train_loader), train_acc / len(train_loader),
eval_loss / len(test_loader), eval_acc / len(test_loader)))
2.4.7可視化損失函數(shù)
2.4.7.1?train? loss?
plt.title('train loss')
plt.plot(np.arange(len(losses)), losses)
plt.legend(['Train Loss'], loc='upper right')
?2.4.7.2?test?loss
# 繪制測試集損失函數(shù)
plt.plot(eval_losses, label='Test Loss')
plt.title('Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()
plt.show()
文章來源:http://www.zghlxwxcb.cn/news/detail-628627.html
?
到了這里,關(guān)于pytorch學(xué)習(xí)——如何構(gòu)建一個神經(jīng)網(wǎng)絡(luò)——以手寫數(shù)字識別為例的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!