從零到一:PyTorch 卷積神經網路 (CNN) 全方位實戰指南

在當前人工智慧爆炸式增長的時代,卷積神經網路 (CNN) 作為電腦視覺 (Computer Vision) 的核心技術,其重要性不言而喻。無論是人臉辨識、自動駕駛還是醫學影像分析,CNN 都扮演著不可或缺的角色。

本文將帶領你深入探索如何使用 PyTorch —— 全球最受歡迎的深度學習框架之一 —— 從頭開始建構、訓練並優化一個高效的 CNN 模型。


1. 環境準備與資料集構建

在開始寫程式碼之前,我們必須確保環境中安裝了 torchtorchvision。在處理影像任務時,好的數據預處理 (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 帳號登入即可留言