卷積神經網路 · 優化器 · 學習率調度
CNN(卷積神經網路)
單篇 ↗CNN(卷積神經網路)
全名:Convolutional Neural Network
介紹:是一種專為處理圖像數據設計的深度學習模型
基本架構:由卷積層、池化層以及全連接層組成
卷積層**(Convolution Layer)**
介紹:把一張圖片的局部特徵提取出來,他透過卷積核(一個小矩陣)在這張圖片上滑動,他能減少圖像的資訊量,同時保留重要特徵
核心任務:自動提取圖像局部特徵
-
用多個「卷積核(filter)」在輸入圖像上滑動,挑出不同小區域的特徵。
-
能夠偵測到如邊緣、紋理、顏色等低階特徵,疊加多層後可抽象出高階特徵如形狀、物體輪廓。
-
這些特徵經由疊層逐層加深,讓模型能夠由簡單的像素資料漸漸「看懂」複雜的物體。
-
詳細介紹
1. 卷積核(Filter/Kernels)與特徵圖(Feature Maps)
-
卷積層使用「卷積核」這種小矩陣在輸入圖像上滑動。
-
每次卷積核覆蓋一小部分圖像,計算內積(像素 X 權重)加總,產生一個新值。
-
這個運算會在整張圖上滑動,最後產生「特徵圖」,記錄某種特徵(如邊緣、紋理)在各位置的強度。
-
通常卷積層不只用一個卷積核,每個核可偵測不同型態的特徵,因此每層可產生多張特徵圖,這些圖會組成下一層的輸入。
2. 運算流程
-
滑動:卷積核從左上到右下,逐一在圖像上各小區域進行運算。
-
內積計算:覆蓋範圍內像素與卷積核權重一一相乘後加總。
-
生成新特徵圖:每個卷積核會產生一個新的特徵圖,代表這種「模式」在整張圖像中的分布與強度。
3. 卷積層的優點與作用
-
自動學習特徵:卷積核的權重通過訓練自動尋找重要特徵,免去人工設計。
-
參數量少,計算效率高:只需處理小區域,極大減少參數和計算。
-
支援多層疊加:低階層提取簡單結構,高階層疊加抽象更複雜的型態(如形狀、物件等)。
-
空間感受野不斷擴大:每往後一層,特徵圖能看見越多來源像素,進而理解物件整體結構。
4. 激活函數與非線性轉換
- 卷積層通常接著「激活函數」(如 ReLU),讓特徵圖能捕捉非線性複雜性。
-
池化層(Pooling Layer)
介紹:將卷積層所生成的特徵圖去進行萃取精華,減少運算量和模型複雜度
主要用途:縮小特徵圖尺寸,減少參數與雜訊
-
最常見為「最大池化(Max Pooling)」,是在小區域裡取最大值代表這區塊。
-
池化有助於保留最重要資訊,同時讓模型對位置變化產生穩定性(平移不變性)。
-
也能減少模型計算量並防止過擬合。
註解:最大池化(Max Pooling)是指把一個區塊的數值找出最大的,把他留下來
-
詳細介紹
1. 核心原理
-
特徵圖下採樣:將原始特徵圖依固定大小(如2×2)區塊切分,對每個小區域進行池化(例如取最大值或平均值)。
-
常見作法:
-
最大池化(Max Pooling):每個區域取最大值。
-
平均池化(Average Pooling):每個區域取平均值。
-
-
滑動窗口:池化區塊根據設定的步幅(stride)滑動,可完全不重疊或部分重疊。
2. 主要功能與優點
-
降低資料維度:壓縮影像寬高,減少神經網路參數和運算量。
-
提升特徵抽象能力:保留最重要特徵,去除雜訊與微小變化。
-
加強空間不變性:例如,圖片出現小幅度平移、旋轉,特徵依然可被辨識,提高模型魯棒性。
-
降低過擬合風險:減少不必要的細節,讓模型專注於主要結構。
3. 池化層設計常見參數
參數 常用設定 作用 kernel (2, 2) 區塊大小,每次看2x2點 stride 2 每次滑動2格,確保不重疊 種類 Max/Average 最常用最大池化,也有平均池化 4. 與卷積層差異
-
卷積層:會自動學習權重,專注於抓出特徵(如邊緣、紋理)。
-
池化層:無需學習參數,專注於壓縮和穩健性,不直接抓新特徵。
5. 常見問題與設計建議
-
池化層不需使用激活函數。
-
池化過強會喪失細節;過弱則無法有效壓縮與泛化。
-
設計CNN時,通常「兩個卷積層後加一個池化層」,控制規模提升效率。
-
全連接層(Fully Connected Layer)
介紹:把前面兩個步驟最後的結果先變成一維數列,並把他們進行分類或預測
任務:最終「分類/判斷」決策中心
-
在此層,所有前面特徵圖會被「攤平」成一串數值,送到全連接神經元。
-
類似傳統神經網路,多數神經元彼此連接,最後配合 Softmax 輸出各類別的機率。
-
詳細介紹
1. 連接方式與運算
-
全部連接:每個神經元與前一層所有神經元都有連接,每一條連接皆有獨立的「權重」和「偏置」值可學習。
-
展平特徵圖:池化層或卷積層的輸出通常是多維特徵圖,進入FC層時會被「攤平成一維向量」。
-
線性組合:每個神經元計算所有輸入值的加權總和,再加偏置值,通常經過激活函數後產生最終輸出。
-
激活函數:常用 ReLU、Sigmoid、Tanh 等。最終分類層多用 Softmax,輸出各類別的機率。
2. 主要功能
-
特徵整合與判斷:FC層將前面提取的所有特徵綜合分析,做最終分類、預測、回歸等任務。
-
類比投票:每個特徵可視為 “投票”,票數(權重)不同,表示特徵重要程度不同。
3. 與卷積層的差異
層次 作用 參數連接方式 卷積層 局部特徵抽取 局部連接,權重共享 全連接層 整體分類判斷 全連接,每對節點一權重 4. 設計注意事項
-
FC層參數量大,容易造成運算負擔;有時使用 “全局平均池化” 或減少FC層數量減輕效能壓力。
-
通常設置在模型尾端,一到兩層即可完成主要任務。
-
資料來源:
相關筆記
- GoogLeNet:經典 CNN 架構
- 激活函數(Rectified Linear Unit)
- 前向傳播(Forward Propagation)
- 反向傳播(Backpropagation)
- 優化器:訓練 CNN 用的優化器
激活函數(Rectified Linear Unit)
單篇 ↗激活函數(Rectified Linear Unit)
-
ReLU 的公式:
-
意思就是:輸入如果小於 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
前向傳播就是把輸入變成模型輸出的過程,是「預測」的本質。
相關筆記
- 激活函數(Rectified Linear Unit):每層輸出經過的非線性
- 損失函數:前向傳播的終點
- 反向傳播(Backpropagation):下一步:計算梯度
損失函數
單篇 ↗損失函數
損失函數就是一個衡量標準,告訴你模型的「預測」和「正確答案」有多接近——越小表示越準確。
訓練神經網路(包括 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 越大」
簡化直觀流程:
-
CNN 輸出每個類別的「得分」(logits),常不是機率
-
CrossEntropyLoss先自動經過 softmax 變成機率分布 -
比較這分布和正確答案(one-hot 或 index)
-
算出整體誤差 loss
其他常見的損失函數(CNN裡也常用)
-
BCEWithLogitsLoss:二元分類(只有 0 或 1—如貓或不是貓)或多標籤(圖可同時屬多個類別)問題
-
MSELoss:回歸問題(預測連續數值)
-
Focal Loss:解決類別極不平衡時,專門加大難分類樣本的權重
相關筆記
- 前向傳播(Forward Propagation):產生預測值
- 反向傳播(Backpropagation):對損失求梯度
- 正則化:加在損失上的懲罰項
- moco.py:實例:對比學習的交叉熵(InfoNCE)損失
反向傳播(Backpropagation)
單篇 ↗反向傳播(Backpropagation)
-
目標:根據 loss,讓模型參數朝「更準」的方向優化。
-
步驟:
-
從 output(損失)開始,沿著神經網路反向往回「流動」誤差資訊
-
透過鏈式法則,逐層算出每個參數對 loss 的影響(即「梯度」)
-
這些梯度(即每個參數該怎麼改)會交給 optimizer(如 SGD、Adam)去更新參數
-
反向傳播就是修正模型讓下一次預測變更準的步驟,是模型「學習」的核心。
相關筆記
- 前向傳播(Forward Propagation):上一步
- 損失函數:梯度的來源
- 優化器:用梯度更新權重
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 (學習率)
- 學習率調度器:多數調度器以 epoch 為單位調整
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-2 | SGD + Momentum | 快速收斂 | 容易震盪 |
| 1e-3 ~ 5e-4 | Adam/AdamW(推薦) | 平衡速度與穩定 | 最常用 |
| 1e-4 ~ 5e-5 | 微調預訓練模型 | 穩定、不破壞原有知識 | 收斂慢 |
| 1e-5 ~ 1e-6 | 超精細調整 | 極度穩定 | 非常慢 |
相關筆記
- 學習率調度器:訓練中動態調整學習率
- 分層學習率 (Layer-wise Learning Rate):不同層用不同學習率
- 優化器:學習率如何被優化器使用
優化器
單篇 ↗優化器
什麼是優化器?
優化器(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)隨機梯度下降:最基本的優化器
- AdaGrad:自適應學習率的起點
- AdaDelta:改善 AdaGrad 學習率遞減
- RMSprop:改善 AdaGrad 學習率遞減
- Adam(Adaptive Moment Estimation):動量 + RMSprop
- AdamW(Adam with Weight Decay):Adam + 解耦權重衰減
- CNN 常見 optimizer 整理表:比較表
- Learning Rate (學習率):優化器的核心超參數
- 學習率調度器:訓練中動態調整學習率
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_decay | L2 正則化 | 1e-4 |
nesterov | Nesterov 加速 | True(可選) |
優點:
-
訓練穩定
-
泛化能力強
-
理論基礎扎實
缺點:
-
需要仔細調整學習率
-
收斂較慢
-
對學習率敏感
適用場景:
-
追求最佳泛化性能
-
訓練 ResNet、VGG 等經典架構
-
有充足時間調參
相關筆記
- 優化器:優化器總覽
- Adam(Adaptive Moment Estimation):加上動量與自適應學習率的進化版
- Learning Rate (學習率):SGD 對學習率特別敏感
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 任務
-
稀疏資料
相關筆記
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 訓練
-
在線學習
相關筆記
- 優化器:優化器總覽
- AdaGrad:前身
- Adam(Adaptive Moment Estimation):RMSprop + 動量
AdaDelta
單篇 ↗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。
相關筆記
- 優化器:優化器總覽
- RMSprop:Adam 的二階動量來源
- AdamW(Adam with Weight Decay):修正 Adam 的 L2 正則化問題
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更好
| 方面 | Adam | AdamW |
|---|---|---|
| Weight Decay | 與自適應學習率耦合 | 解耦,效果更好 |
| 正則化效果 | 較弱 | 較強 |
| 泛化能力 | 一般 | 更好 |
優點:
-
結合 Adam 的速度
-
正確的正則化
-
更好的泛化能力
-
適合從零訓練和微調
缺點:
- 比 SGD 泛化能力略差(但比 Adam 好)
適用場景:
-
首選優化器
-
CNN、Transformer、任何深度學習模型
-
從零訓練或微調預訓練模型
相關筆記
- Adam(Adaptive Moment Estimation):前身
- 權重衰減(Weight Decay):AdamW 解耦的就是這一項
- 正則化:權重衰減屬於正則化
- 中國醫RAG專案說明:實例:Contriever 檢索模型訓練
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 訓練集 | 新模型先驗證「能不能學」、想快速得到不錯結果時,很適合當預設 |
| AdamW | Adam + 正確的 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
單篇 ↗MultiStepLR
是在 StepLR 基礎上更「可客製化」的一種階梯式衰減
在你指定的幾個 epoch(里程碑)把 lr 變小
核心直覺:MultiStepLR 在做什麼?
-
StepLR:每隔固定
step_sizeepoch 扣一次學習率 -
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]這種
相關筆記
- 學習率調度器:調度器總覽
- StepLR - 階梯式衰減:固定間隔衰減的版本
ExponentialLR - 指數衰減
單篇 ↗ExponentialLR - 指數衰減
原理: 每個 epoch 學習率乘以固定係數
公式直觀版:
-
:初始學習率
-
t:第幾個 epoch
-
:例如 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 = 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 搭配時很適合 |
相關筆記
- 學習率調度器:各調度器詳細說明
- CNN 常見 optimizer 整理表:搭配使用的優化器比較
分層學習率 (Layer-wise Learning Rate)
單篇 ↗分層學習率 (Layer-wise Learning Rate)
為什麼需要分層學習率?
概念: 不同層使用不同的學習率
原因:
-
預訓練模型微調:前面的層已經學到很好的特徵,不應該大幅改動
-
不同層的重要性:越靠近輸出層,越需要針對任務調整
-
訓練穩定性:避免破壞底層的良好特徵
比喻:
想像一個熟練的廚師(預訓練模型):
- 基本刀工(前幾層):已經很熟練,只需微調 → 小學習率
- 調味技巧(中間層):需要適應新口味 → 中學習率
- 菜單設計(最後層):完全重新學習 → 大學習率
實作範例
範例 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
經驗法則:
-
底層 → 頂層:學習率逐漸增大(通常 10 倍關係)
-
預訓練模型:底層 1e-6 ~ 1e-5,頂層 1e-3 ~ 1e-2
-
從零訓練:各層學習率差異不要太大(3-5 倍即可)
權重衰減梯度:
層級 Weight Decay
─────────────────────────────
Input Layer 1e-5 (輕)
Middle Layer 1e-4 (中)
Output Layer 1e-3 ~ 1e-2 (重)
相關筆記
- Learning Rate (學習率):基本概念
- AdamW(Adam with Weight Decay):微調預訓練模型時常搭配使用
正則化
單篇 ↗正則化
重點就一個:想辦法減少 overfitting,讓模型在看不見的新資料上表現更好。
正則化 = 對模型「下限制 / 加懲罰」,不要讓它在訓練集上學得太複雜、太偏激。
在 CNN 常見的正則化手法只要先記住幾個名字就好:
-
L2 / weight decay:限制權重不要太大
-
Dropout:隨機把部份神經元關掉
-
Data augmentation:把圖片做旋轉、翻轉、裁切當作更多樣本
-
Early stopping:驗證集變差就提前停訓練
這些方法的共同目標:犧牲一點訓練集表現,換更好的泛化能力。
相關筆記
- 權重衰減(Weight Decay):最常見的正則化方式
- 損失函數:正則項加在損失函數上
權重衰減(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 | 過強 | 可能導致欠擬合 |
相關筆記
- AdamW(Adam with Weight Decay):在優化器中解耦權重衰減
- 正則化:正則化總覽
GoogLeNet
單篇 ↗GoogLeNet
介紹:GoogLeNet(又稱Inception v1)是Google於2014年發表,並在ImageNet比賽中獲得冠軍的卷積神經網路模型。其最大創新是引入了「Inception Module」多尺度並聯結構,在精確度和效率之間達到突破。
GoogLeNet 的優缺點
優點
-
參數量少、訓練快
-
多尺度設計創新,精度相對高
-
為後續 Inception 系列奠定基礎
缺點
-
層數多、計算複雜度高
-
後來 ResNet 用殘差連接更容易訓練
-
現在較少單獨用,多作為對比或教學用途
相關筆記
- Inception:GoogLeNet 的核心模組
- GoogLeNet 層級參數解釋:逐層參數
- CNN(卷積神經網路)
Inception
單篇 ↗Inception
在 GoogLeNet 裡指的是一種「特別設計的卷積模組」,是整個 GoogLeNet 架構的核心積木。可以把它想成:同一層裡,同時用好幾種不同大小的卷積和池化,然後把結果拼在一起,來達到「多尺度特徵提取 + 降計算量」的效果。
相關筆記
- GoogLeNet:使用 Inception 模組的網路
- 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)。這是最後的「大腦」,做最終判斷。 |