1. 自動求導機制
概念解釋:
- 自動求導:PyTorch的
autograd
模塊允許我們自動計算張量的梯度,這在反向傳播算法中尤為重要。反向傳播是神經網絡訓練的核心,用于計算每個參數的梯度并更新參數。
生活中的例子:
想象你是一個廚師,正在調整一個菜譜,使它更加美味。每次你改變一個配料的量,比如鹽或糖,你都會嘗試這個菜,然后根據味道的變化決定是否需要進一步調整。這就像在神經網絡中計算梯度:你調整網絡的參數(配料),觀察輸出(菜的味道),然后根據輸出的變化來更新參數(調整配料)。
示例代碼:
import torchx = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
y = x + 2
z = y * y * 3
out = z.mean()print("x:", x)
print("y:", y)
print("z:", z)
print("out:", out)
運行結果:
x: tensor([1., 2., 3.], requires_grad=True)
y: tensor([3., 4., 5.], grad_fn=<AddBackward0>)
z: tensor([27., 48., 75.], grad_fn=<MulBackward0>)
out: tensor(50., grad_fn=<MeanBackward0>)
解釋:
requires_grad=True
:表示我們需要計算x
的梯度。y = x + 2
:對每個元素加2。z = y * y * 3
:每個元素先平方,再乘以3。out = z.mean()
:計算張量的平均值。
計算圖與梯度計算:
out.backward()
print(x.grad)
運行結果:
tensor([ 4., 8., 12.])
解釋:out
相對于x
的梯度是4*x + 4
。
梯度計算公式:
- y = x + 2 y = x + 2 y=x+2
- z = 3 y 2 z = 3y^2 z=3y2
- o u t = 1 3 ∑ z out = \frac{1}{3} \sum z out=31?∑z
反向傳播:
- ? o u t ? z i = 1 3 \frac{\partial out}{\partial z_i} = \frac{1}{3} ?zi??out?=31?
- ? z i ? y i = 6 y i \frac{\partial z_i}{\partial y_i} = 6y_i ?yi??zi??=6yi?
- ? y i ? x i = 1 \frac{\partial y_i}{\partial x_i} = 1 ?xi??yi??=1
所以:
? o u t ? x i = 1 3 × 6 y i × 1 = 2 y i \frac{\partial out}{\partial x_i} = \frac{1}{3} \times 6y_i \times 1 = 2y_i ?xi??out?=31?×6yi?×1=2yi?
而 y i = x i + 2 y_i = x_i + 2 yi?=xi?+2,所以:
? o u t ? x i = 2 ( x i + 2 ) \frac{\partial out}{\partial x_i} = 2(x_i + 2) ?xi??out?=2(xi?+2)
當 x = [ 1 , 2 , 3 ] x = [1, 2, 3] x=[1,2,3] 時:
? o u t ? x = [ 4 , 8 , 12 ] \frac{\partial out}{\partial x} = [4, 8, 12] ?x?out?=[4,8,12]
torch.autograd.Variable
:
現在torch.Tensor
已經取代了Variable
,并且默認情況下所有張量都支持自動求導,所以Variable
不再需要單獨使用。
2. 構建簡單神經網絡
概念解釋:
- 神經網絡:神經網絡是一種模仿人腦工作方式的計算模型。它由許多相互連接的“神經元”組成,每個神經元接收輸入信號并產生輸出信號。
nn.Module
類:是所有神經網絡模塊的基類。自定義的神經網絡類需要繼承nn.Module
并實現其方法。
生活中的例子:
想象你正在教一個機器人識別不同類型的水果。你給機器人看各種水果的圖片,并告訴它們每個水果的名稱。機器人通過觀察這些圖片并學習它們的特征(比如顏色、形狀),逐漸學會區分不同的水果。這就像神經網絡通過訓練數據學習模式。
示例代碼:
import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(784, 256)self.fc2 = nn.Linear(256, 10)def forward(self, x):x = F.relu(self.fc1(x))x = self.fc2(x)return xnet = Net()
print(net)
運行結果:
Net((fc1): Linear(in_features=784, out_features=256, bias=True)(fc2): Linear(in_features=256, out_features=10, bias=True)
)
解釋:
__init__
方法中定義了兩個全連接層(fc1
和fc2
)。forward
方法定義了前向傳播的過程,首先通過第一層,然后應用ReLU激活函數,最后通過第二層。
前向傳播:
input = torch.randn(1, 784)
output = net(input)
print(output)
運行結果:
tensor([[ 0.0520, 0.2651, 0.0512, -0.1564, -0.2470, -0.2246, 0.0936, -0.2600,0.1607, 0.1467]], grad_fn=<AddmmBackward>)
解釋:生成一個隨機輸入張量input
,通過網絡得到輸出output
。
損失函數和優化器:
概念解釋:
- 損失函數:用來衡量模型輸出與實際目標之間的差異。
- 優化器:通過反向傳播計算梯度并更新模型參數,以最小化損失函數。
生活中的例子:
想象你在考試中答錯了一些題目,老師告訴你哪些題目答錯了,并給你一些建議。你根據這些建議修改你的學習方法,下次考試爭取做得更好。損失函數就像老師的反饋,優化器就像你調整學習方法的過程。
示例代碼:
import torch.optim as optimcriterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)# 示例訓練步驟
optimizer.zero_grad() # 清除梯度
output = net(input) # 前向傳播
loss = criterion(output, torch.tensor([1])) # 計算損失
loss.backward() # 反向傳播
optimizer.step() # 更新權重
解釋:
criterion
:定義損失函數,這里使用交叉熵損失函數。optimizer
:定義優化器,這里使用隨機梯度下降(SGD)。optimizer.zero_grad()
:清除梯度。output = net(input)
:前向傳播。loss = criterion(output, torch.tensor([1]))
:計算損失。loss.backward()
:反向傳播,計算梯度。optimizer.step()
:更新權重。
3. 訓練流程
概念解釋:
- 數據加載與處理:使用
torch.utils.data
模塊加載和處理數據。
生活中的例子:
想象你在準備一個大餐,需要從市場購買食材。你需要將所有食材分成不同的類別,并按照菜譜中的要求進行處理和烹飪。數據加載和處理就像你從市場獲取食材,并準備它們以便進一步使用。
示例代碼:
from torch.utils.data import DataLoader, TensorDataset# 示例數據
inputs = torch.randn(100, 784)
targets = torch.randint(0, 10, (100,))dataset = TensorDataset(inputs, targets)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
解釋:
inputs
和targets
:生成示例數據。TensorDataset
:將輸入和目標數據打包成數據集。DataLoader
:加載數據集,支持批處理和打亂數據。
定義模型、損失函數和優化器:
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)
解釋:定義模型、損失函數和優化器。
訓練循環:
for epoch in range(2): # 訓練2個epochfor inputs, targets in dataloader:optimizer.zero_grad() # 清除梯度outputs = net(inputs) # 前向傳播loss = criterion(outputs, targets) # 計算損失loss.backward() # 反向傳播optimizer.step() # 更新權重print(f"Epoch {epoch+1}, Loss: {loss.item()}")
**
運行結果**:
Epoch 1, Loss: 2.303864002227783
Epoch 2, Loss: 2.3021395206451416
解釋:訓練2個epoch,每個epoch中對每個批次數據進行前向傳播、計算損失、反向傳播和更新權重。
模型評估與驗證:
概念解釋:
- 評估模式:在評估模式下,不計算梯度,節省內存和計算資源。
生活中的例子:
想象你準備了一個大餐,現在邀請朋友來品嘗。他們給你反饋,你記錄這些反饋以便改進菜譜。這就像模型評估,你不再調整參數,而是觀察模型在新數據上的表現。
示例代碼:
net.eval() # 進入評估模式
with torch.no_grad():inputs = torch.randn(10, 784)outputs = net(inputs)predicted = torch.argmax(outputs, dim=1)print(predicted)
運行結果:
tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
解釋:
net.eval()
:將模型設置為評估模式。torch.no_grad()
:禁用梯度計算,節省內存和計算資源。predicted
:預測的類別。