快轉到主要內容
  1. 教學文章/

PyTorch 神經網路入門:從零開始建立你的第一個模型

·5 分鐘· loading · loading · ·
Python Pytorch Neural-Network Deep-Learning Machine-Learning
每日拍拍
作者
每日拍拍
科學家 X 科技宅宅
目錄
Python 學習 - 本文屬於一個選集。
§ 21: 本文

一. 前言
#

你有沒有想過,ChatGPT、影像辨識、語音助理背後的核心技術是什麼?答案就是神經網路 (Neural Network)

雖然「深度學習」聽起來很嚇人,但其實用 Python + PyTorch,幾十行程式碼就能建出一個能學習的模型。今天拍拍君就來手把手帶你從零開始,用 PyTorch 建立你的第一個神經網路!

🎯 本文目標:理解 Tensor、自動微分、模型定義、訓練迴圈,並完成一個手寫數字辨識模型。

二. 安裝
#

# 用 pip 安裝(CPU 版本,入門足夠)
pip install torch torchvision

# 或用 uv
uv pip install torch torchvision

確認安裝成功:

import torch
print(torch.__version__)       # e.g., 2.6.0
print(torch.cuda.is_available())  # GPU 是否可用

💡 如果你有 NVIDIA GPU,可以裝 CUDA 版本加速訓練。Mac M 系列晶片則可以用 torch.backends.mps

三. Tensor:PyTorch 的核心資料結構
#

Tensor(張量)就是 PyTorch 版本的多維陣列,跟 NumPy 的 ndarray 很像,但多了兩個超能力:自動微分GPU 加速

import torch

# 建立 Tensor
x = torch.tensor([1.0, 2.0, 3.0])
print(x)          # tensor([1., 2., 3.])
print(x.shape)    # torch.Size([3])
print(x.dtype)    # torch.float32

# 常用建立方式
zeros = torch.zeros(3, 4)        # 3×4 全零
ones = torch.ones(2, 3)          # 2×3 全一
rand = torch.randn(2, 3)         # 2×3 標準常態分佈
arange = torch.arange(0, 10, 2)  # [0, 2, 4, 6, 8]

Tensor 運算
#

a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])

# 元素運算
print(a + b)       # tensor([5., 7., 9.])
print(a * b)       # tensor([ 4., 10., 18.])

# 矩陣運算
A = torch.randn(3, 4)
B = torch.randn(4, 5)
C = A @ B          # 矩陣乘法,結果 shape: (3, 5)

# reshape
x = torch.arange(12).reshape(3, 4)
print(x.shape)     # torch.Size([3, 4])

NumPy 互轉
#

import numpy as np

# NumPy → Tensor
np_arr = np.array([1, 2, 3])
tensor = torch.from_numpy(np_arr)

# Tensor → NumPy
back_to_np = tensor.numpy()

⚠️ 兩者共享記憶體,改一個另一個也會變!如果不想共享,用 .clone().copy()

四. Autograd:自動微分
#

神經網路的學習靠的是梯度下降 (Gradient Descent),而 PyTorch 的 autograd 系統會自動幫你算梯度,不用手推微分!

# 告訴 PyTorch 要追蹤這個變數的梯度
x = torch.tensor(3.0, requires_grad=True)

# 定義函數 y = x^2 + 2x + 1
y = x ** 2 + 2 * x + 1

# 反向傳播,計算 dy/dx
y.backward()

# dy/dx = 2x + 2 = 2(3) + 2 = 8
print(x.grad)  # tensor(8.)

更實際的例子 — 向量梯度:

w = torch.randn(3, requires_grad=True)
x = torch.tensor([1.0, 2.0, 3.0])

# 前向計算
z = (w * x).sum()
z.backward()

print(w.grad)  # 就是 x: tensor([1., 2., 3.])

🧠 backward() 會沿著計算圖反向傳播,自動算出每個 requires_grad=True 變數的偏微分。這就是深度學習的數學基礎!

五. 建立神經網路模型
#

PyTorch 用 torch.nn 模組來定義模型。最常用的方式是繼承 nn.Module

import torch.nn as nn

class SimpleNet(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super().__init__()
        self.layer1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.layer2 = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        x = self.layer1(x)    # 線性變換
        x = self.relu(x)      # 激活函數
        x = self.layer2(x)    # 輸出層
        return x

# 建立模型
model = SimpleNet(input_size=784, hidden_size=128, num_classes=10)
print(model)

輸出:

SimpleNet(
  (layer1): Linear(in_features=784, out_features=128, bias=True)
  (relu): ReLU()
  (layer2): Linear(in_features=128, out_features=10, bias=True)
)

快速版:用 nn.Sequential
#

如果模型是簡單的堆疊結構,可以更精簡:

model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 10),
)

常用層和激活函數
#

層 / 函數 用途
nn.Linear(in, out) 全連接層(線性變換)
nn.Conv2d(in_ch, out_ch, kernel) 2D 卷積層(影像用)
nn.ReLU() 激活函數(最常用)
nn.Sigmoid() 輸出 0~1(二元分類)
nn.Softmax(dim=1) 輸出機率分佈(多類分類)
nn.Dropout(p) 隨機丟棄(防過擬合)
nn.BatchNorm1d(n) 批次正規化(加速訓練)

六. 完整範例:MNIST 手寫數字辨識
#

把上面學到的全部串起來!我們用經典的 MNIST 資料集來訓練一個能辨識手寫數字的模型。

6.1 準備資料
#

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

# 資料預處理:轉 Tensor + 正規化
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081,)),  # MNIST 的均值和標準差
])

# 下載 MNIST
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, transform=transform)

# DataLoader:批次載入 + 打亂
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)

6.2 定義模型
#

class MNISTNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()            # 28×28 → 784
        self.layers = nn.Sequential(
            nn.Linear(784, 256),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(128, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        return self.layers(x)

model = MNISTNet()

6.3 設定損失函數和優化器
#

criterion = nn.CrossEntropyLoss()             # 多類分類的標準損失
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
優化器 特點
SGD 最經典,需要調 learning rate
Adam 自適應學習率,大多數情況首選
AdamW Adam + weight decay,訓練大模型常用

6.4 訓練迴圈
#

這是深度學習最核心的部分:

def train(model, loader, criterion, optimizer, epoch):
    model.train()  # 設為訓練模式(啟用 Dropout 等)
    total_loss = 0

    for batch_idx, (data, target) in enumerate(loader):
        optimizer.zero_grad()       # 1. 清除舊梯度
        output = model(data)        # 2. 前向傳播
        loss = criterion(output, target)  # 3. 計算損失
        loss.backward()             # 4. 反向傳播(算梯度)
        optimizer.step()            # 5. 更新權重

        total_loss += loss.item()

    avg_loss = total_loss / len(loader)
    print(f"Epoch {epoch}: avg loss = {avg_loss:.4f}")

🔁 訓練五步驟口訣:清梯度 → 前向 → 算損失 → 反向 → 更新

6.5 評估模型
#

def evaluate(model, loader):
    model.eval()  # 設為評估模式(關閉 Dropout)
    correct = 0
    total = 0

    with torch.no_grad():  # 評估時不需要算梯度
        for data, target in loader:
            output = model(data)
            pred = output.argmax(dim=1)
            correct += (pred == target).sum().item()
            total += target.size(0)

    accuracy = 100.0 * correct / total
    print(f"Test accuracy: {accuracy:.2f}%")
    return accuracy

6.6 開始訓練!
#

num_epochs = 10

for epoch in range(1, num_epochs + 1):
    train(model, train_loader, criterion, optimizer, epoch)
    evaluate(model, test_loader)

典型輸出:

Epoch 1: avg loss = 0.3521
Test accuracy: 95.42%
Epoch 5: avg loss = 0.0812
Test accuracy: 97.63%
Epoch 10: avg loss = 0.0398
Test accuracy: 97.89%

🎉 只用簡單的全連接網路,就能達到 ~98% 的準確率!用 CNN 可以輕鬆到 99%+。

七. 進階技巧
#

儲存和載入模型
#

# 儲存(只存權重,推薦)
torch.save(model.state_dict(), 'mnist_model.pth')

# 載入
model = MNISTNet()
model.load_state_dict(torch.load('mnist_model.pth'))
model.eval()

GPU 加速
#

# 選擇裝置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# Mac M 系列:
# device = torch.device('mps' if torch.backends.mps.is_available() else 'cpu')

# 把模型和資料搬到 GPU
model = model.to(device)

# 訓練時也要搬資料
for data, target in train_loader:
    data, target = data.to(device), target.to(device)
    output = model(data)
    # ...

Learning Rate Scheduler
#

scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.5)

for epoch in range(1, num_epochs + 1):
    train(model, train_loader, criterion, optimizer, epoch)
    evaluate(model, test_loader)
    scheduler.step()  # 每 5 個 epoch 把 lr 砍半

結語
#

今天我們從最基礎的 Tensor 開始,一路走到完成一個能辨識手寫數字的神經網路模型。回顧一下學到的重點:

  1. Tensor — PyTorch 的基本資料結構,支援 GPU 加速
  2. Autograd — 自動微分,不用手推梯度
  3. nn.Module — 模型定義的標準方式
  4. 訓練迴圈 — 清梯度 → 前向 → 損失 → 反向 → 更新
  5. 評估model.eval() + torch.no_grad()

PyTorch 的設計哲學是 Pythonic + 動態計算圖,寫起來就像普通 Python,debug 也很直覺。這也是為什麼它成為學術界和業界最受歡迎的深度學習框架之一。

下一步你可以試試:

  • CNN (nn.Conv2d) 來做影像辨識
  • RNN/LSTM 來處理序列資料
  • Hugging Face 玩預訓練模型

深度學習的世界很大,但第一步其實沒那麼難。加油!💪

延伸閱讀
#

Python 學習 - 本文屬於一個選集。
§ 21: 本文

相關文章

Ruff:用 Rust 寫的 Python Linter,快到你會懷疑人生
·4 分鐘· loading · loading
Python Ruff Linter Formatter Code-Quality
少寫一半程式碼:dataclasses 讓你的 Python 類別煥然一新
·6 分鐘· loading · loading
Python Dataclasses Oop 標準庫
超快速 Python 套件管理:uv 完全教學
·6 分鐘· loading · loading
Python Uv Package Manager Rust
Python asyncio 非同步程式設計入門:讓你的程式不再傻等
·8 分鐘· loading · loading
Python Asyncio 非同步 並行
用 Typer 打造專業 CLI 工具:Python 命令列框架教學
·10 分鐘· loading · loading
Python Typer Cli 開發工具
Python 資料驗證小幫手:Pydantic
·4 分鐘· loading · loading
Python Pydantic Data Validation