LinDragon 筆記圖書館2026年10月
Journal of CNN

卷積神經網路 · 優化器 · 學習率調度

特輯 · 29 篇連讀

CNN 全集

卷積神經網路 · 優化器 · 學習率調度

CNN(卷積神經網路)

單篇 ↗

CNN(卷積神經網路)

全名:Convolutional Neural Network

介紹:是一種專為處理圖像數據設計的深度學習模型

基本架構:由卷積層、池化層以及全連接層組成


卷積層**(Convolution Layer)**

介紹:把一張圖片的局部特徵提取出來,他透過卷積核(一個小矩陣)在這張圖片上滑動,他能減少圖像的資訊量,同時保留重要特徵

核心任務:自動提取圖像局部特徵

  • 用多個「卷積核(filter)」在輸入圖像上滑動,挑出不同小區域的特徵。

  • 能夠偵測到如邊緣、紋理、顏色等低階特徵,疊加多層後可抽象出高階特徵如形狀、物體輪廓。​

  • 這些特徵經由疊層逐層加深,讓模型能夠由簡單的像素資料漸漸「看懂」複雜的物體。

  • 詳細介紹

    1. 卷積核(Filter/Kernels)與特徵圖(Feature Maps)

    • 卷積層使用「卷積核」這種小矩陣在輸入圖像上滑動。

    • 每次卷積核覆蓋一小部分圖像,計算內積(像素 X 權重)加總,產生一個新值。

    • 這個運算會在整張圖上滑動,最後產生「特徵圖」,記錄某種特徵(如邊緣、紋理)在各位置的強度。​

    • 通常卷積層不只用一個卷積核,每個核可偵測不同型態的特徵,因此每層可產生多張特徵圖,這些圖會組成下一層的輸入。

    2. 運算流程

    1. 滑動:卷積核從左上到右下,逐一在圖像上各小區域進行運算。

    2. 內積計算:覆蓋範圍內像素與卷積核權重一一相乘後加總。

    3. 生成新特徵圖:每個卷積核會產生一個新的特徵圖,代表這種「模式」在整張圖像中的分布與強度。

    3. 卷積層的優點與作用

    • 自動學習特徵:卷積核的權重通過訓練自動尋找重要特徵,免去人工設計。​

    • 參數量少,計算效率高:只需處理小區域,極大減少參數和計算。

    • 支援多層疊加:低階層提取簡單結構,高階層疊加抽象更複雜的型態(如形狀、物件等)。​

    • 空間感受野不斷擴大:每往後一層,特徵圖能看見越多來源像素,進而理解物件整體結構。

    4. 激活函數與非線性轉換

    • 卷積層通常接著「激活函數」(如 ReLU),讓特徵圖能捕捉非線性複雜性。

池化層(Pooling Layer)

介紹:將卷積層所生成的特徵圖去進行萃取精華,減少運算量和模型複雜度

主要用途:縮小特徵圖尺寸,減少參數與雜訊

  • 最常見為「最大池化(Max Pooling)」,是在小區域裡取最大值代表這區塊。

  • 池化有助於保留最重要資訊,同時讓模型對位置變化產生穩定性(平移不變性)。​

  • 也能減少模型計算量並防止過擬合。

註解:最大池化(Max Pooling)是指把一個區塊的數值找出最大的,把他留下來

  • 詳細介紹

    1. 核心原理

    • 特徵圖下採樣:將原始特徵圖依固定大小(如2×2)區塊切分,對每個小區域進行池化(例如取最大值或平均值)。

    • 常見作法:

      • 最大池化(Max Pooling):每個區域取最大值。

      • 平均池化(Average Pooling):每個區域取平均值。

    • 滑動窗口:池化區塊根據設定的步幅(stride)滑動,可完全不重疊或部分重疊。

    2. 主要功能與優點

    • 降低資料維度:壓縮影像寬高,減少神經網路參數和運算量。

    • 提升特徵抽象能力:保留最重要特徵,去除雜訊與微小變化。

    • 加強空間不變性:例如,圖片出現小幅度平移、旋轉,特徵依然可被辨識,提高模型魯棒性。​

    • 降低過擬合風險:減少不必要的細節,讓模型專注於主要結構。

    3. 池化層設計常見參數

    參數常用設定作用
    kernel(2, 2)區塊大小,每次看2x2點
    stride2每次滑動2格,確保不重疊
    種類Max/Average最常用最大池化,也有平均池化

    4. 與卷積層差異

    • 卷積層:會自動學習權重,專注於抓出特徵(如邊緣、紋理)。

    • 池化層:無需學習參數,專注於壓縮和穩健性,不直接抓新特徵。

    5. 常見問題與設計建議

    • 池化層不需使用激活函數。

    • 池化過強會喪失細節;過弱則無法有效壓縮與泛化。

    • 設計CNN時,通常「兩個卷積層後加一個池化層」,控制規模提升效率。


全連接層(Fully Connected Layer)

介紹:把前面兩個步驟最後的結果先變成一維數列,並把他們進行分類或預測

任務:最終「分類/判斷」決策中心

  • 在此層,所有前面特徵圖會被「攤平」成一串數值,送到全連接神經元。

  • 類似傳統神經網路,多數神經元彼此連接,最後配合 Softmax 輸出各類別的機率。

  • 詳細介紹

    1. 連接方式與運算

    • 全部連接:每個神經元與前一層所有神經元都有連接,每一條連接皆有獨立的「權重」和「偏置」值可學習。

    • 展平特徵圖:池化層或卷積層的輸出通常是多維特徵圖,進入FC層時會被「攤平成一維向量」。

    • 線性組合:每個神經元計算所有輸入值的加權總和,再加偏置值,通常經過激活函數後產生最終輸出。

    • 激活函數:常用 ReLU、Sigmoid、Tanh 等。最終分類層多用 Softmax,輸出各類別的機率。

    2. 主要功能

    • 特徵整合與判斷:FC層將前面提取的所有特徵綜合分析,做最終分類、預測、回歸等任務。​

    • 類比投票:每個特徵可視為 “投票”,票數(權重)不同,表示特徵重要程度不同。

    3. 與卷積層的差異

    層次作用參數連接方式
    卷積層局部特徵抽取局部連接,權重共享
    全連接層整體分類判斷全連接,每對節點一權重

    4. 設計注意事項

    • FC層參數量大,容易造成運算負擔;有時使用 “全局平均池化” 或減少FC層數量減輕效能壓力。

    • 通常設置在模型尾端,一到兩層即可完成主要任務。


資料來源:


相關筆記

激活函數(Rectified Linear Unit)

單篇 ↗

激活函數(Rectified Linear Unit)

  • ReLU 的公式:ReLU(x)=max⁡(0,x)ReLU(x)=max⁡(0,x)

  • 意思就是:輸入如果小於 0,就變 0;大於等於 0,就保持原樣

為什麼 CNN 要用激活函數

如果每一層都只有線性運算(例如卷積 + 加法),整個深度網路其實等價於一個大的線性變換,學不出複雜的非線性特徵。
激活函數的角色是「在每層之間加上非線性」,讓 CNN 可以學到像邊緣、形狀、物體等複雜模式。

ReLU 在 CNN 裡做了什麼

  • 將負值全部壓成 0,留下正值不變 → 特徵變得「稀疏」,有點像「不重要的神經元直接關掉」。​

  • 因為它只是做 max(0, x),計算非常簡單,很快,也適合在大規模 CNN 中使用。​

  • 對於正區域,導數是 1,不會像 Sigmoid 那樣導數接近 0 容易造成梯度消失,所以更適合深層網路。​


ReLU 的優點(為什麼 CNN 常用它)

  • 計算簡單:只做一個比較和取最大值,很快。​

  • 減少梯度消失:在正區間梯度是常數 1,有利於深層網路訓練。​

  • 讓輸出稀疏:很多神經元輸出直接變 0,有助於一定程度的正則化和特徵選擇。​

  • 在大量實作上,效果很好,是目前深度學習中最主流的隱藏層激活選擇之一。​


ReLU 的缺點與變體

  • 缺點:如果某些神經元的輸入長期為負,它們輸出一直是 0,梯度也變成 0,這些神經元就「死掉」了,稱為「dead ReLU」問題。​

  • 常見改進:

    • Leaky ReLU:讓負區域也保留一點點斜率(例如 0.01x),減少死神經元。​

    • Parametric ReLU、ELU 等也是為了改善類似問題。


相關筆記

前向傳播(Forward Propagation)

單篇 ↗

前向傳播(Forward Propagation)

  • 一張圖片進入 CNN,資料會「逐層經過」卷積層、池化層、全連接層等

  • 每一層會做特徵提取和轉換

  • 最終產生預測(如:每個類別的分數或機率)

  • 結果和正解標籤一起丟進損失函數,得到 loss

前向傳播就是把輸入變成模型輸出的過程,是「預測」的本質。


相關筆記

損失函數

單篇 ↗

損失函數

損失函數就是一個衡量標準,告訴你模型的「預測」和「正確答案」有多接近——越小表示越準確。
訓練神經網路(包括 CNN)時,每一步「優化」其實就是試著把這個 loss 變小。


為什麼 CNN 必須有損失函數?

你可以想成:

  • 模型給每張圖做預測(outputs)

  • 真正的正解標籤(labels)已知

  • 把 outputs、labels 丟給損失函數

  • 得到一個數字 loss,代表這批預測的「總誤差」

  • 最終 optimizer (SGD, Adam…)就是根據這個 loss 來更新所有權重


多分類 CNN 常用的損失函數:交叉熵 CrossEntropyLoss

  • **PyTorch 實作最常見就是 nn.CrossEntropyLoss()**​

  • 一次處理一個 batch,輸入形狀是 (batch, 類別數),標籤是每張圖的正確類別

  • 這個 loss 函數自帶 softmax + log,無需你自己在模型裡加 softmax 層

  • 他的物理解釋可以想成:「正確類別的預測機率越大,loss 越小;錯的機率越大,loss 越大」

簡化直觀流程:

  1. CNN 輸出每個類別的「得分」(logits),常不是機率

  2. CrossEntropyLoss 先自動經過 softmax 變成機率分布

  3. 比較這分布和正確答案(one-hot 或 index)

  4. 算出整體誤差 loss​

其他常見的損失函數(CNN裡也常用)

  • BCEWithLogitsLoss:二元分類(只有 0 或 1—如貓或不是貓)或多標籤(圖可同時屬多個類別)問題

  • MSELoss:回歸問題(預測連續數值)

  • Focal Loss:解決類別極不平衡時,專門加大難分類樣本的權重


相關筆記

反向傳播(Backpropagation)

單篇 ↗

反向傳播(Backpropagation)

  • 目標:根據 loss,讓模型參數朝「更準」的方向優化。

  • 步驟:

    • 從 output(損失)開始,沿著神經網路反向往回「流動」誤差資訊

    • 透過鏈式法則,逐層算出每個參數對 loss 的影響(即「梯度」)

    • 這些梯度(即每個參數該怎麼改)會交給 optimizer(如 SGD、Adam)去更新參數

反向傳播就是修正模型讓下一次預測變更準的步驟,是模型「學習」的核心。


相關筆記

Epoch (訓練週期)

單篇 ↗

Epoch (訓練週期)

只訓練模型過程中,演算法完整使用過資料及每筆資料的狀態。

Batch size(批次)

把資料分成一堆堆,分別丟入類神經網路中訓練,而非全部一起丟進去訓練。

Iteration(迭代)

在機器學習上Iteration跟Batch size有關,如果有設定Batch size大小,就會有批次處理資料,就要用迴圈把資料輸入進行訓練。

ex:有100筆資料,一次訓練其中10筆資料,10次迴圈才算是1個Epoch

原始資料大小=Iteration×Batch size=1 Epoch


資料來源:

Epoch, Batch size, Iteration, Learning Rate - 人工智慧,倒底有多智慧? - Medium

Epoch(時期)、Batch size(批次)、Iteration(迭代)、Learning rate - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天


相關筆記

Learning Rate (學習率)

單篇 ↗

Learning Rate (學習率)

定義:控制每次更新參數時「跨出的步伐大小」

# 科學記號 = 係數 × 10^指數
1e-1  = 1 × 10^(-1) = 0.1
1e-2  = 1 × 10^(-2) = 0.01
1e-3  = 1 × 10^(-3) = 0.001
5e-4  = 5 × 10^(-4) = 0.0005
1e-4  = 1 × 10^(-4) = 0.0001
1e-5  = 1 × 10^(-5) = 0.00001
1e-6  = 1 × 10^(-6) = 0.000001

學習率選擇指南

學習率範圍適用場景特點風險
1e-1 ~ 1e-2SGD + Momentum快速收斂容易震盪
1e-3 ~ 5e-4Adam/AdamW(推薦)平衡速度與穩定最常用
1e-4 ~ 5e-5微調預訓練模型穩定、不破壞原有知識收斂慢
1e-5 ~ 1e-6超精細調整極度穩定非常慢

相關筆記

優化器

單篇 ↗

優化器

什麼是優化器?

優化器(Optimizer)是深度學習中負責更新模型參數的演算法,目標是找到讓損失函數(Loss)最小的參數組合。

簡單比喻:

  • 模型參數 = 登山路線

  • 損失函數 = 海拔高度

  • 優化器 = 導航系統

  • 目標 = 找到最低點(山谷)

優化器在做什麼?

每次訓練迭代:
1. 前向傳播:計算預測結果
2. 計算損失:比較預測與真實值
3. 反向傳播:計算梯度
4. 優化器更新:調整參數
   ↓
   參數_new = 參數_old - 學習率 × 梯度

動量 = 對「過去梯度的指向」做指數平均,再用這個平均來更新權重。

主要效果:加速收斂、減少震盪、幫助跳出小局部最小值,對 CNN 特別有用。

SGD(Stochastic Gradient Descent)隨機梯度下降.md

Adam(Adaptive Moment Estimation).md

AdamW(Adam with Weight Decay).md

RMSprop.md

AdaGrad.md

AdaDelta.md

使用場景建議

# 🎯 場景 1:一般 CNN 訓練(影像分類、物體偵測)
優先選擇: AdamW
備選: SGD + Momentum

# 🎯 場景 2:Transformer、BERT、GPT
首選: AdamW
學習率: 1e-4 ~ 5e-5

# 🎯 場景 3:RNN、LSTM
優先選擇: AdamW 或 RMSprop
學習率: 1e-3

# 🎯 場景 4:微調預訓練模型
首選: AdamW(分層學習率)
學習率: 1e-5 (backbone) + 1e-3 (classifier)

# 🎯 場景 5:從零訓練大型模型
首選: AdamW
學習率: 1e-3(搭配學習率調度器)

# 🎯 場景 6:追求極致準確率(有時間調參)
首選: SGD + Momentum
學習率: 0.01(搭配 StepLR 或 CosineAnnealingLR)

# 🎯 場景 7:快速實驗、驗證想法
首選: Adam 或 AdamW
學習率: 1e-3

相關筆記

SGD(Stochastic Gradient Descent)隨機梯度下降

單篇 ↗

SGD(Stochastic Gradient Descent)隨機梯度下降

最常用的優化器之一,用來一步一步調整權重,讓 loss 變小。

核心概念:每次只看「一小批(mini‑batch)」資料算梯度,而不是整個訓練集,來更新參數。

為什麼叫「Stochastic(隨機)」?

  • 傳統 batch gradient descent:每一步都用「全部訓練資料」算一次梯度,更新一次參數,對大數據非常慢、也吃記憶體。

  • SGD:每步只用「一個樣本」或「一個小 batch」算梯度,樣本是隨機抽的,所以每次看到的梯度都帶有「隨機噪音」。

  • 好處:

    • 每一步計算量小,更新很頻繁,訓練大規模 CNN 時特別實用。

    • 因為有噪音,路徑會「抖一抖」,比較有機會跳出壓在局部極小值或鞍點附近的狀態。

特點:最基本的優化器,簡單但有效

optimizer = optim.SGD(
    model.parameters(),
    lr=0.01,           # 學習率(通常需要較大值)
    momentum=0.9,      # 動量(加速收斂,減少震盪)
    weight_decay=1e-4, # 權重衰減
    nesterov=False     # 是否使用 Nesterov 動量
)

參數說明:

參數說明推薦值
lr學習率0.01 ~ 0.1
momentum動量係數0.9
weight_decayL2 正則化1e-4
nesterovNesterov 加速True(可選)

優點:

  • 訓練穩定

  • 泛化能力強

  • 理論基礎扎實

缺點:

  • 需要仔細調整學習率

  • 收斂較慢

  • 對學習率敏感

適用場景:

  • 追求最佳泛化性能

  • 訓練 ResNet、VGG 等經典架構

  • 有充足時間調參


相關筆記

AdaGrad

單篇 ↗

AdaGrad

常被更新的參數:步伐越來越小
很少被更新的參數:步伐相對比較大

特點:自動調整學習率,適合稀疏資料

optimizer = optim.Adagrad(
    model.parameters(),
    lr=1e-2,           # 初始學習率(可以設大一點)
    lr_decay=0,        # 學習率衰減
    weight_decay=0,    # 權重衰減
    eps=1e-10          # 數值穩定性
)

也就是說,它會根據「過去累積的梯度大小」來調整每個參數的 learning rate:

  • 梯度累積很大 → 覺得這個參數已經調很多了 → 之後更新變小

  • 梯度累積很小 → 覺得還沒怎麼調過 → 之後可以走大一點

AdaGrad 有個很大的問題:

  • 它對「過去所有梯度」做累積,時間一久,有效 learning rate 會越來越小,小到幾乎不動

  • 所以訓練後期可能變得超級慢,甚至像停住一樣

  • 後來才有 RMSprop、Adam 這些改良版出來解決這個問題

優點:

  • 不需手動調整學習率

  • 適合稀疏梯度

缺點:

  • 學習率衰減過快

  • 後期幾乎不更新

適用場景:

  • NLP 任務

  • 稀疏資料


相關筆記

  • 優化器:優化器總覽
  • AdaDelta:解決 AdaGrad 學習率持續遞減
  • RMSprop:用指數移動平均取代累加

RMSprop

單篇 ↗

RMSprop

可以先把它當成「自動調整 learning rate 的加強版 SGD」

RMSprop 會根據「最近一段時間的梯度大小」,自動幫每個參數調整步伐大小

特點:Adam的前身,適合RNN

直觀感覺:

  • 某個參數的梯度常常很大 → RMSprop 會讓它走「小步」,避免亂跳

  • 某個參數的梯度一直很小 → 讓它走「大一點的步」,避免卡住不動

所以它特別適合:

  • 梯度很「不穩定」的情況(例如 RNN、強化學習),CNN 也常用

  • 想要比純 SGD 更穩定、更快收斂,但又不一定要用到 Adam

optimizer = optim.RMSprop(
    model.parameters(),
    lr=1e-3,           # 學習率
    alpha=0.99,        # 平滑常數
    eps=1e-8,          # 數值穩定性
    weight_decay=0,    # 權重衰減
    momentum=0         # 動量
)

和 Adam / SGD 比較

  • 跟 SGD 比:

    • RMSprop:每個參數都有「自己的動態 lr」,通常收斂更穩、更快
  • 跟 Adam 比:

    • RMSprop:只看「梯度平方的平均」,

    • Adam:同時看「梯度平均」+「梯度平方平均」,通常更好調、也更常當預設

優點:

  • 適合非平穩目標

  • 適合 RNN/LSTM

缺點:

  • 不如 Adam/AdamW 流行

  • 調參較麻煩

適用場景:

  • RNN、LSTM 訓練

  • 在線學習


相關筆記

AdaDelta

單篇 ↗

AdaDelta

特點:AdaGrad的改進版,不需要設定初始學習率

optimizer = optim.Adadelta(
    model.parameters(),
    rho=0.9,           # 衰減率
    eps=1e-6,          # 數值穩定性
    weight_decay=0     # 權重衰減
)

優點:

  • 不需要初始學習率

  • 解決 AdaGrad 學習率衰減問題

缺點:

  • 不如 Adam/AdamW 流行

  • 收斂可能較慢


相關筆記

Adam(Adaptive Moment Estimation)

單篇 ↗

Adam(Adaptive Moment Estimation)

在 SGD 基礎上,自動幫每個參數調 learning rate,還順便幫你加好 momentum。

可以把 Adam 想成:

  • 自動幫你加好「動量」,讓 loss 比較平滑下降(不會亂抖)

  • 自動幫「每個參數」調整合適的步伐(learning rate),不需要你一直調來調去

特點:自適應學習率,每個參數有獨立的學習率

optimizer = optim.Adam(
    model.parameters(),
    lr=1e-3,                  # 學習率
    betas=(0.9, 0.999),       # 一階和二階動量的衰減率
    eps=1e-8,                 # 數值穩定性
    weight_decay=0,           # 注意:在 Adam 中不建議使用
    amsgrad=False             # 是否使用 AMSGrad 變體
)

參數說明:

參數說明推薦值
lr學習率1e-3 ~ 1e-4
betas(β1, β2) 動量參數(0.9, 0.999)
eps防止除零1e-8
weight_decay不建議使用0

數學原理(簡化):

m_t = β1 × m_(t-1) + (1-β1) × gradient     # 一階動量
v_t = β2 × v_(t-1) + (1-β2) × gradient²    # 二階動量
weight_new = weight - lr × m_t / (√v_t + ε)

優點:

  • 收斂快速

  • 對學習率不敏感

  • 適合大多數問題

缺點:

  • weight_decay 實作有問題(使用 AdamW 代替)

  • 泛化能力略遜於 SGD

  • 容易在訓練後期震盪

什麼情況我會建議你用 Adam?

  • 剛設計一個新 CNN 架構,想先確定「這個模型有沒有基本可學性」:用 Adam,好收斂

  • 資料不是超級大、你比較在意「快點收斂到一個 ok 的結果」而不是 squeeze 出最後 1~2%:用 Adam

  • 你目前還不太熟調 learning rate schedule:用 Adam 可以少踩坑一點

等你比較熟了,想追更好泛化(test accuracy)時,可以再嘗試從 Adam 換成 SGD+Momentum。


相關筆記

AdamW(Adam with Weight Decay)

單篇 ↗

AdamW(Adam with Weight Decay)

AdamW 跟 Adam 的核心差別(直觀)
AdamW = 「Adam + 正確的 weight decay(L2 正則化)」

重點不是“多了 weight decay”,而是:

  • Adam:把 L2 正則化「混在梯度裡面」一起算

  • AdamW:把 weight decay「從梯度更新裡分離開,直接對權重做衰減」

這個「分離」(decouple)讓:

  • 正則化效果更乾淨,對 overfitting 控制通常比較好

  • 學習率的行為更穩,不會被 L2 搞亂更新方向​

實務上很多人現在會把 AdamW 當成「比 Adam 更好的預設選擇」。

特點:修正了Adam的weight_decay問題,目前最推薦的優化器

optimizer = optim.AdamW(
    model.parameters(),
    lr=1e-3,                  # 學習率
    betas=(0.9, 0.999),       # 動量參數
    eps=1e-8,                 # 數值穩定性
    weight_decay=1e-4,        # 正確的權重衰減
    amsgrad=False
)

為什麼AdamW更好

方面AdamAdamW
Weight Decay與自適應學習率耦合解耦,效果更好
正則化效果較弱較強
泛化能力一般更好

優點:

  • 結合 Adam 的速度

  • 正確的正則化

  • 更好的泛化能力

  • 適合從零訓練和微調

缺點:

  • 比 SGD 泛化能力略差(但比 Adam 好)

適用場景:

  • 首選優化器

  • CNN、Transformer、任何深度學習模型

  • 從零訓練或微調預訓練模型


相關筆記

CNN 常見 optimizer 整理表

單篇 ↗

CNN 常見 optimizer 整理表

Optimizer核心特色(直觀)優點(實務感受)缺點 / 注意什麼時候可以選它?
SGD固定步伐往「平均梯度反方向」走簡單、可控;調好 + schedule 時,泛化常很好需要小心調 learning rate,容易震盪、收斂慢想要「最經典」、在大資料/分類任務追最好 test accuracy 時常用(搭配 momentum、LR schedule)
SGD + Momentum在 SGD 上加「慣性」,往穩定方向加速比純 SGD 收斂快、路徑更平滑超參數多一點,需要調 momentum、LR做圖像分類時很常見的強力 baseline,想追高泛化時常會換成這個
Adam每個參數有自己的動量 + 自適應 LR起步容易、收斂快、對 LR 不太敏感;預設值就常能用泛化有時略輸 SGD+Momentum;對某些任務會過度 fit 訓練集新模型先驗證「能不能學」、想快速得到不錯結果時,很適合當預設
AdamWAdam + 正確的 weight decay(解耦 L2)泛化通常比 Adam 好些;收斂穩、效率佳,很多研究發現是很平衡的選擇​仍然是 adaptive optimizer,有時仍不如 SGD 在極致泛化上想要 Adam 的方便/速度,又在意正則化與穩定收斂時,很推薦當 CNN 預設​
RMSprop根據「最近梯度平方平均」調每參數 LR在梯度不穩的問題上更穩定;比純 SGD 通常容易訓練行為比 Adam 原始一點;超參數(alpha)要懂一點意思傳統上在 RNN、強化學習常見;在 CNN 中可當 Adam 的替代實驗方案​
AdaGrad按「累積梯度平方」調整 LR:越常更新,LR 越小自動減小步伐;適合稀疏特徵、NLP 早期常用​LR 會持續變小,後期幾乎不動 → 收斂停滯理解歷史概念、做對照實驗用;現代 CNN 實務較少作為主力
AdaDelta改良 AdaGrad:只看「最近一段梯度」,避免 LR 歸零不用顯式設定初始 LR 也能跑;能持續更新,不易卡死​表現依任務而異,很多研究裡準確率通常不是最頂​想試不同 adaptive optimizer、對 LR 不想太手調時,可作備選,但 CNN 實務也不算主流

相關筆記

學習率調度器

單篇 ↗

學習率調度器

在訓練過程中自動幫你改 learning rate 的工具,而不是整個訓練都用同一個 lr

為什麼需要?

  • 訓練初期:大學習率,快速接近最佳解

  • 訓練後期:小學習率,精細調整

StepLR - 階梯式衰減.md

MultiStepLR.md

ExponentialLR - 指數衰減.md

CosineAnnealingLR - 餘弦退火.md

ReduceLROnPlateau - 自適應衰減.md


相關筆記

StepLR - 階梯式衰減

單篇 ↗

StepLR - 階梯式衰減

原理: 每隔固定 epoch 將學習率乘以衰減係數

optimizer = optim.AdamW(model.parameters(), lr=1e-3)
scheduler = optim.lr_scheduler.StepLR(
    optimizer,
    step_size=30,    # 每 30 個 epoch 衰減一次
    gamma=0.1        # 衰減係數(lr = lr × 0.1)
)

# 使用方式
for epoch in range(100):
    train(...)
    scheduler.step()  # 每個 epoch 結束後調用
  • 設定:step_size = S,gamma = γ

  • 意思:每過 S 個 epoch,就把現在的 lr 變成原來的 γ 倍

  • 效果:學習率曲線長得像樓梯:一段時間保持不變 → 突然掉一級 → 再保持 → 再掉

學習率變化:

Epoch    Learning Rate
0-29     1e-3
30-59    1e-4  (×0.1)
60-89    1e-5  (×0.1)
90-99    1e-6  (×0.1)

可視化:

Learning Rate
  │
1e-3│████████████████████████████
  │
1e-4│                            ████████████████████████████
  │
1e-5│                                                        ████████████
  │
  └─────────────────────────────────────────────────────────────→
    0        30        60        90       Epoch

什麼時候適合用 StepLR?

  • 很多 分類 CNN(像 ResNet, CIFAR-10, ImageNet) 會用:

    • 例如:epoch 30、60、90 各衰減一次
  • 優點:簡單、好理解、效果常不錯

  • 缺點:lr 是「突然跳變」,不是平滑下降

  • 適用: 訓練 epoch 數固定的情況


相關筆記

MultiStepLR

單篇 ↗

MultiStepLR

是在 StepLR 基礎上更「可客製化」的一種階梯式衰減

在你指定的幾個 epoch(里程碑)把 lr 變小

核心直覺:MultiStepLR 在做什麼?

  • StepLR:每隔固定 step_size epoch 扣一次學習率

  • MultiStepLR:你「自己指定幾個 epoch 點」,在那些點扣學習率

所以你會給一個列表 milestones=[e1, e2, e3, ...]:

  • 當 epoch 到 e1 時 → lr *= gamma

  • 到 e2 時 → 再乘一次 gamma

  • 以此類推

lr 曲線還是「樓梯狀」,但樓梯在哪幾階是你自己決定的,而不是固定間隔。


PyTorch CNN 寫法(感覺一下就好)

optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)

scheduler = torch.optim.lr_scheduler.MultiStepLR(
    optimizer,
    milestones=[30, 60, 90],  # 在這幾個 epoch 把 lr 衰減
    gamma=0.1                 # 每次乘 0.1
)

for epoch in range(num_epochs):
    train_one_epoch(...)
    scheduler.step()

意思就是:

  • epoch 0–29:lr = 0.1

  • epoch 30–59:lr = 0.01

  • epoch 60–89:lr = 0.001

  • epoch 90 之後:0.0001


為什麼用 MultiStepLR?

  • 比 StepLR 更靈活:你可以根據實驗經驗選在「模型快收斂完一段」時再降 lr

  • 很多論文或實作會寫:milestones=[30, 60, 80] 這種


相關筆記

ExponentialLR - 指數衰減

單篇 ↗

ExponentialLR - 指數衰減

原理: 每個 epoch 學習率乘以固定係數

公式直觀版:

lrt=lr0×γtlr _ t =lr _ 0 ×γ ^ t
  • lr0lr_0:初始學習率

  • t:第幾個 epoch

  • γ<1γ<1:例如 0.95、0.99 → 每個 epoch 都乘一次

  • 每個 epoch 都按同一比例變小

  • 曲線是「平滑指數下降」,不像 StepLR / MultiStepLR 那樣一階一階突然掉

optimizer = optim.AdamW(model.parameters(), lr=1e-3)
scheduler = optim.lr_scheduler.ExponentialLR(
    optimizer,
    gamma=0.95  # lr = lr × 0.95 (每個 epoch)
)

學習率變化:

Epoch   Learning Rate
0       1.000e-3
10      0.599e-3  (×0.95^10)
20      0.358e-3  (×0.95^20)
50      0.077e-3  (×0.95^50)
100     0.006e-3  (×0.95^100)

適用: 需要緩慢平滑衰減的場景


相關筆記

CosineAnnealingLR - 餘弦退火

單篇 ↗

CosineAnnealingLR - 餘弦退火

原理: 學習率按餘弦曲線平滑衰減

像餘弦曲線一樣先慢慢降,再升回來一點,常配合長訓練

  • 從初始 lr 開始,慢慢降到 eta_min(通常接近 0)

  • 降的形狀是「半個餘弦」,一開始降得快,後面越來越慢

  • 常用來:前期大步探索,後期很細地微調參數

沒有像 StepLR 那樣「突然掉階梯」,是整個訓練過程中平滑彎下來

optimizer = optim.AdamW(model.parameters(), lr=1e-3)
scheduler = optim.lr_scheduler.CosineAnnealingLR(
    optimizer,
    T_max=100,      # 週期長度(總 epoch 數)
    eta_min=1e-6    # 最小學習率
)

學習率變化公式:

lr=etamin+(lrmax−etamin)×(1+cos(π×epoch/Tmax))/2lr = etamin + (lrmax - etamin) × (1 + cos(π × epoch / Tmax)) / 2
lr = eta_min + (lr_max - eta_min) × (1 + cos(π × epoch / T_max)) / 2

可視化:

Learning Rate
    │
1e-3│╲
    │ ╲
    │  ╲
    │   ╲___
    │       ╲___
    │           ╲___
1e-6│               ╲______
    │
    └─────────────────────────→
    0    25   50   75   100  Epoch

優點:

  • 平滑衰減

  • 避免學習率突變

  • 適合從零訓練

  • 幾乎不用指定很多「里程碑」,只設定 T_max 就好

  • 比 StepLR / MultiStepLR 更平滑,有時收斂更穩定

適用: 從零訓練、訓練時間較長的任務


相關筆記

ReduceLROnPlateau - 自適應衰減

單篇 ↗

ReduceLROnPlateau - 自適應衰減

原理: 當指標停止改善時自動降低學習率

當「模型表現卡住一陣子沒進步」時,才自動把學習率變小

核心概念(只抓這個)

  • 你指定要「監控的指標」,例如:

    • 驗證 loss(希望越小越好 → mode=‘min’)

    • 驗證 accuracy(希望越大越好 → mode=‘max’)

  • 如果這個指標在好幾個 epoch 內都沒變好(叫做 plateau 平台期):
    → 就把 lr 乘上一個 factor(例如 0.1),讓 lr 變小,幫助模型再往更細的方向收斂。​

直覺就是:
「訓練卡住不進步 → 自動幫你調小 lr 再試試看」。

optimizer = optim.AdamW(model.parameters(), lr=1e-3)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(
    optimizer,
    mode='max',      # 'max' 監控準確率, 'min' 監控 loss
    factor=0.5,      # 衰減係數(lr = lr × 0.5)
    patience=3,      # 容忍 3 個 epoch 沒進步
    verbose=True,    # 顯示學習率變化
    min_lr=1e-7      # 最小學習率
)

# 使用方式
for epoch in range(100):
    train(...)
    val_acc = validate(...)
    scheduler.step(val_acc)  # 傳入監控指標

幾個關鍵參數直觀理解:​

  • mode:‘min’(指標越小越好)或 ‘max’(越大越好)

  • factor:每次衰減倍率,通常 0.1 或 0.2

  • patience:容忍多少個「沒進步的 epoch」才動手降 lr

  • min_lr:lr 不會小於這個值

  • cooldown:剛降完 lr,要等多少 epoch 才開始再次監控,避免太頻繁降

運作示例:

Epoch   Val Acc   Learning Rate   說明
1       75.0%     1e-3            初始
2       78.0%     1e-3            進步 
3       80.0%     1e-3            進步 
4       80.5%     1e-3            進步 
5       80.3%     1e-3            沒進步 (patience 1/3)
6       80.4%     1e-3            沒進步 (patience 2/3)
7       80.2%     1e-3            沒進步 (patience 3/3)
8       80.3%     5e-4 ⬇          觸發衰減!
9       81.0%     5e-4            進步(重置 patience)

優點:

  • 自動調整

  • 不需預先設定

  • 適應不同訓練速度

缺點:

  • 可能過早衰減

適用: 不確定訓練會跑多久、微調任務


相關筆記

學習率調度器 整理表

單篇 ↗

學習率調度器 整理表

Scheduler學習率變化形狀(直觀)主要參數重點優點缺點 / 注意CNN 何時適合用?
StepLR像樓梯:一段時間不變,到了某個 epoch 突然降一階​step_size:隔幾個 epoch 降一次;gamma:每次乘多少(如 0.1)實作簡單;常見設定(如 30, 60, 90)在分類 CNN 上很好用lr 是「突然跳變」;需要事先猜大概什麼 epoch 降​做 CIFAR‑10/Imagenet 類 CNN,照論文設定 epoch 30/60/90 衰減,很常見的 baseline
MultiStepLR還是樓梯,但「哪幾階要降」自己指定​milestones=[30,60,90] 等;gamma 同上比 StepLR 更靈活,適合你已經有想好的關鍵 epoch里程碑要自己設,錯設可能浪費訓練跟隨某篇 paper 的 schedule 時,用 MultiStepLR 很方便直接對齊
ExponentialLR平滑指數曲線:每個 epoch 都按固定比例慢慢變小​gamma:每步乘的比例(0.9、0.95、0.99 等)不用設里程碑;lr 連續變化、不會突然跳早期降得太快或太慢要靠經驗調 gamma ​想要「一直慢慢變小」的簡單策略,訓練時間預估不準時也好用
CosineAnnealingLR半個餘弦形狀:一開始降比較快,後期很平滑地貼近 0​T_max:一個「餘弦周期」的 epoch 數;eta_min:最低 lr幾乎不用選很多點;長訓練常有不錯效果,收斂穩定需要大概知道訓練總 epoch(好設 T_max)​訓練 ResNet/大 CNN 跑很多 epoch,又懶得設一堆 milestones 時,很推薦
ReduceLROnPlateau沒固定形狀:看驗證集有沒有進步,卡住一段時間才降​mode(看 min 或 max)、factor(衰減倍數)、patience(多久沒進步才降)真正「自適應」:loss/acc 不進步才降 lr,比較聰明​必須用驗證指標來 step();調 patience 等參數要點經驗​你不確定什麼時候該降 lr,或想用 early‑stopping+動態 lr 搭配時很適合

相關筆記

分層學習率 (Layer-wise Learning Rate)

單篇 ↗

分層學習率 (Layer-wise Learning Rate)

為什麼需要分層學習率?

概念: 不同層使用不同的學習率

原因:

  1. 預訓練模型微調:前面的層已經學到很好的特徵,不應該大幅改動

  2. 不同層的重要性:越靠近輸出層,越需要針對任務調整

  3. 訓練穩定性:避免破壞底層的良好特徵

比喻:

想像一個熟練的廚師(預訓練模型):
- 基本刀工(前幾層):已經很熟練,只需微調 → 小學習率
- 調味技巧(中間層):需要適應新口味 → 中學習率
- 菜單設計(最後層):完全重新學習 → 大學習率

實作範例

範例 1:CNN 微調(如 GoogLeNet)

optimizer = optim.AdamW([
    # 前面的卷積層(低階特徵)
    {'params': model.conv1.parameters(), 
     'lr': 1e-5, 'weight_decay': 1e-4},
    {'params': model.conv2.parameters(), 
     'lr': 1e-5, 'weight_decay': 1e-4},
    
    # 中間的 Inception 層(中階特徵)
    {'params': model.inception3a.parameters(), 
     'lr': 5e-5, 'weight_decay': 5e-4},
    {'params': model.inception3b.parameters(), 
     'lr': 5e-5, 'weight_decay': 5e-4},
    
    # 後面的 Inception 層(高階特徵)
    {'params': model.inception5a.parameters(), 
     'lr': 1e-4, 'weight_decay': 1e-3},
    {'params': model.inception5b.parameters(), 
     'lr': 1e-4, 'weight_decay': 1e-3},
    
    # 分類層(任務相關)
    {'params': model.fc.parameters(), 
     'lr': 1e-3, 'weight_decay': 1e-2}
])

範例 2:簡化版(3 組)

optimizer = optim.AdamW([
    # 組 1:底層特徵(凍結或微調)
    {'params': [
        *model.layer1.parameters(),
        *model.layer2.parameters()
    ], 'lr': 1e-5, 'weight_decay': 1e-4},
    
    # 組 2:中層特徵
    {'params': [
        *model.layer3.parameters(),
        *model.layer4.parameters()
    ], 'lr': 1e-4, 'weight_decay': 5e-4},
    
    # 組 3:分類層
    {'params': model.fc.parameters(), 
     'lr': 1e-3, 'weight_decay': 1e-2}
])

設定原則

學習率梯度:

層級          學習率      倍數關係
─────────────────────────────────
Input Layer   1e-6       ×1
Layer 1-2     1e-5       ×10
Layer 3-4     5e-5       ×50
Layer 5-6     1e-4       ×100
Layer 7-8     5e-4       ×500
Output Layer  1e-3       ×1000

經驗法則:

  1. 底層 → 頂層:學習率逐漸增大(通常 10 倍關係)

  2. 預訓練模型:底層 1e-6 ~ 1e-5,頂層 1e-3 ~ 1e-2

  3. 從零訓練:各層學習率差異不要太大(3-5 倍即可)

權重衰減梯度:

層級          Weight Decay
─────────────────────────────
Input Layer   1e-5 (輕)
Middle Layer  1e-4 (中)
Output Layer  1e-3 ~ 1e-2 (重)

相關筆記

正則化

單篇 ↗

正則化

重點就一個:想辦法減少 overfitting,讓模型在看不見的新資料上表現更好。

正則化 = 對模型「下限制 / 加懲罰」,不要讓它在訓練集上學得太複雜、太偏激。

在 CNN 常見的正則化手法只要先記住幾個名字就好:

  • L2 / weight decay:限制權重不要太大

  • Dropout:隨機把部份神經元關掉

  • Data augmentation:把圖片做旋轉、翻轉、裁切當作更多樣本

  • Early stopping:驗證集變差就提前停訓練

這些方法的共同目標:犧牲一點訓練集表現,換更好的泛化能力。


相關筆記

權重衰減(Weight Decay)

單篇 ↗

權重衰減(Weight Decay)

定義:懲罰過大的權重值,防止過擬合

作用:

  • 限制模型複雜度

  • 防止權重爆炸

  • 提升泛化能力

數學原理

標準更新公式:

weight_new = weight - lr × gradient

加入 weight decay:

weight_new = weight - lr × gradient - lr × weight_decay × weight
                                      ↑
                                  這部分會讓權重逐漸變小

實際範例:

# 當前權重
weight = 10.0

# 訓練參數
lr = 0.001
gradient = -5.0
weight_decay = 0.0001

# 沒有 weight_decay
weight_new = 10.0 - 0.001 × (-5.0)
           = 10.0 + 0.005
           = 10.005

# 有 weight_decay
weight_new = 10.0 - 0.001 × (-5.0) - 0.001 × 0.0001 × 10.0
           = 10.0 + 0.005 - 0.000001
           = 10.004999  ← 權重被壓制了一點

3.3 效果展示

權重大小
  │
  │ ╱‾‾‾‾‾‾‾‾╲ 
  │╱          ╲    ← 無 weight_decay:權重可能過大
  │            ╲
  │             ╲___
  │                  ╲
  │___________________╲___  ← 有 weight_decay:權重被限制
  訓練過程 →

過擬合 vs 正則化:

訓練準確率 vs 驗證準確率

無正則化(weight_decay=0):
Train: 95% ████████████████
Val:   75% ██████████        ← 過擬合!差距 20%

適度正則化(weight_decay=1e-4):
Train: 88% █████████████
Val:   85% ████████████      ← 健康!差距 3%

過度正則化(weight_decay=1e-2):
Train: 70% █████████
Val:   68% █████████         ← 欠擬合!都太低

選擇指南

Weight Decay效果適用場景
0無正則化資料量大、模型簡單
1e-5極輕微輕微過擬合
1e-4標準(推薦)一般情況
5e-4中等明顯過擬合
1e-3較強嚴重過擬合
1e-2很強極度過擬合
>1e-2過強可能導致欠擬合

相關筆記

GoogLeNet

單篇 ↗

GoogLeNet

介紹:GoogLeNet(又稱Inception v1)是Google於2014年發表,並在ImageNet比賽中獲得冠軍的卷積神經網路模型。其最大創新是引入了「Inception Module」多尺度並聯結構,在精確度和效率之間達到突破。

GoogLeNet 的優缺點

優點

  • 參數量少、訓練快

  • 多尺度設計創新,精度相對高

  • 為後續 Inception 系列奠定基礎

缺點

  • 層數多、計算複雜度高

  • 後來 ResNet 用殘差連接更容易訓練

  • 現在較少單獨用,多作為對比或教學用途


相關筆記

Inception

單篇 ↗

Inception

在 GoogLeNet 裡指的是一種「特別設計的卷積模組」,是整個 GoogLeNet 架構的核心積木。可以把它想成:同一層裡,同時用好幾種不同大小的卷積和池化,然後把結果拼在一起,來達到「多尺度特徵提取 + 降計算量」的效果。


相關筆記

GoogLeNet 層級參數解釋

單篇 ↗

GoogLeNet 層級參數解釋

Stem 層(前處理 + 初始特徵提取)

層名位置/功能參數內容直觀角色
conv1.parameters()最前面的 7×7 卷積層第一個大卷積核 (3→64 通道, stride=2) 的權重和 bias從原始 RGB 圖片抽出最基本的特徵(邊緣、顏色梯度、簡單紋理)。這是整個網路的「眼睛」,直接面對輸入影像。
conv2.parameters()第二個 1×1 + 3×3 卷積組合兩個小卷積層的權重 (64→192 通道)對 conv1 的輸出做更細緻的特徵提煉,開始出現多尺度處理的雛形。
conv3.parameters()第三個卷積 + 池化前處理最後一個 stem 卷積 (192→192 或類似)過渡層,準備進入 Inception 模組,特徵圖大小通常在這裡降到 28×28 或更小。

Inception 3 模組(中低階特徵)

層名位置/功能參數內容直觀角色
inception3a.parameters()第一個 Inception 模組4 個平行分支的卷積核 (1×1, 3×3, 5×5, pool)開始多尺度學習:同時看細節(1×1)、中等形狀(3×3)、大範圍特徵(5×5)。輸出通道約 256。
inception3b.parameters()Inception 3 的第二個模組類似 3a,但通道數略增 (約 480 輸出)深化特徵提取,在 3a 基礎上學更複雜的模式,特徵圖大小通常維持或略降。

Inception 4 模組(中高階特徵 + 輔助分類器)

層名位置/功能參數內容直觀角色
inception4a.parameters()Inception 4 開頭通道數增加到約 512 的 Inception 模組特徵更豐富,這裡通常會接一個輔助分類器 (aux1),用來穩定深層訓練(解決梯度消失)。
inception4b-d.parameters()Inception 4 中間 3 個模組持續深化,通道數維持 512 左右穩定特徵學習階段,每個模組都捕捉不同尺度的語意資訊(如物體部位關係)。
inception4e.parameters()Inception 4 結尾最後一個 512 通道 Inception,通常後接 max pooling過渡到更深層,特徵圖大小降到約 7×7,準備進入最終階段。

Inception 5 模組(高階語意特徵)

層名位置/功能參數內容直觀角色
inception5a.parameters()倒數第二階段通道數激增到 832 的 Inception 模組高階語意提取:學整個物體的概念、場景理解。這裡的特徵已經很抽象。
inception5b.parameters()最後一個 Inception 模組輸出 1024 通道,通常接 global average pooling最終特徵壓縮,把所有層的資訊整合成最豐富的表示,準備分類。

分類頭

層名位置/功能參數內容直觀角色
fc.parameters()最後的全連接層1024→num_classes 的線性變換權重分類決策層:把前面所有特徵映射到最終的類別分數(例如 1000 類 ImageNet)。這是最後的「大腦」,做最終判斷。

相關筆記

iT 邦幫忙!一起幫忙解決難題,拯救 IT 人的一天

單篇 ↗