從零到一:PyTorch 卷積神經網路 (CNN) 全方位實戰指南
在當前人工智慧爆炸式增長的時代,卷積神經網路 (CNN) 作為電腦視覺 (Computer Vision) 的核心技術,其重要性不言而喻。無論是人臉辨識、自動駕駛還是醫學影像分析,CNN 都扮演著不可或缺的角色。
本文將帶領你深入探索如何使用 PyTorch —— 全球最受歡迎的深度學習框架之一 —— 從頭開始建構、訓練並優化一個高效的 CNN 模型。
1. 環境準備與資料集構建
在開始寫程式碼之前,我們必須確保環境中安裝了 torch 與 torchvision。在處理影像任務時,好的數據預處理 (Data Augmentation) 是成功的關鍵。
1.1 使用 Dataset 與 DataLoader
PyTorch 提供了強大的 Dataset 類別,讓我們可以輕鬆處理數以萬計的影像。
import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# 定義數據增強與正規化
transform = transforms.Compose([
transforms.RandomHorizontalFlip(), # 隨機水平翻轉
transforms.RandomRotation(10), # 隨機旋轉
transforms.ToTensor(), # 轉換為張量
transforms.Normalize((0.5,), (0.5,)) # 正規化至 [-1, 1]
])
# 載入 MNIST 資料集作為範例
train_set = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_set, batch_size=64, shuffle=True)
這段代碼中,我們使用了 DataLoader 來進行 Batching。這能有效地利用 GPU 的平行計算能力,避免記憶體溢位。
2. CNN 神經網路架構設計
一個標準的 CNN 通常由多組「卷積層 + 激活函數 + 池化層」堆疊而成,最後再加上全連接層進行分類。
2.1 建構模型類別
我們將設計一個名為 AdvancedCNN 的網路,它具有更深的結構與 Dropout 層來防止過擬合。
import torch.nn as nn
import torch.nn.functional as F
class AdvancedCNN(nn.Module):
def __init__(self):
super(AdvancedCNN, self).__init__()
# 卷積層 1:提取基礎特徵(線條、邊緣)
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(32) # 批次歸一化提高訓練穩定性
# 卷積層 2:提取複雜特徵(紋理、局部形狀)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.bn2 = nn.BatchNorm2d(64)
self.pool = nn.MaxPool2d(2, 2)
self.dropout = nn.Dropout(0.25)
# 全連接層
self.fc1 = nn.Linear(64 * 7 * 7, 512)
self.fc2 = nn.Linear(512, 10)
def forward(self, x):
# 第一組卷積
x = self.pool(F.relu(self.bn1(self.conv1(x))))
# 第二組卷積
x = self.pool(F.relu(self.bn2(self.conv2(x))))
# 展平與全連接
x = x.view(-1, 64 * 7 * 7)
x = self.dropout(F.relu(self.fc1(x)))
x = self.fc2(x)
return x
3. 訓練流程與損失函數優化
模型寫好後,如何教導它「學習」?這涉及到 損失函數 (Loss Function) 與 優化器 (Optimizer) 的選擇。
3.1 選擇 Loss 與 Optimizer
對於多分類任務,CrossEntropyLoss 是標準選擇,它結合了 LogSoftmax 與 NLLLoss。
model = AdvancedCNN().to('cuda' if torch.cuda.is_available() else 'cpu')
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
3.2 訓練迴圈 (Training Loop)
訓練過程是反覆進行「前向傳播 (Forward)」、「計算損失」、「反向傳播 (Backward)」與「權重更新 (Update)」的過程。
epochs = 10
for epoch in range(epochs):
running_loss = 0.0
for images, labels in train_loader:
# 清空梯度
optimizer.zero_grad()
# 前向傳播
outputs = model(images)
loss = criterion(outputs, labels)
# 反向傳播
loss.backward()
# 更新權重
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}")
4. 模型評估與結果輸出
訓練完成後,我們必須在測試集上評估模型的泛化能力。單純看訓練損失是不夠的,我們需要關注 準確率 (Accuracy) 與 混淆矩陣 (Confusion Matrix)。
4.1 輸出結果
correct = 0
total = 0
with torch.no_grad(): # 評估模式不計算梯度
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(f'Test Accuracy: {100 * correct / total:.2f}%')
5. 總結與展望
在本指南中,我們完整走過了一遍深度學習的實戰流程。從資料的準備、網路架構的搭建、訓練策略的擬定到最後的結果評估。
5.1 關鍵要點回顧
- 數據增強:能夠有效提升模型的抗干擾能力。
- BatchNorm:是現代深度網路快速收斂的祕訣。
- Dropout:是防止模型死背硬記(過擬合)的利器。
深度學習是一個不斷實驗的過程。你可以嘗試調整 學習率 (Learning Rate)、更換不同的 激活函數 (Activation Function) 或者增加層數。每一次失敗的嘗試都是通往正確模型的必經之路。
希望這篇文章能為你的 AI 探索之路提供一份有價值的地圖!
留言
使用 GitHub 帳號登入即可留言