Python | OpenCV 避免過擬合
📚 前言
在上一篇 資料增強 中,我們學會了透過增強訓練資料來提升泛化能力。
這一篇介紹另一個關鍵主題:避免過擬合 (Overfitting)。
資料增強是「讓模型看更多種類的圖片」,而這一篇的方法是「限制模型過度記憶訓練資料」。兩者都是提升泛化能力的手段,但切入角度不同,通常會一起使用。
本篇會先說明如何判斷過擬合,再介紹四種常用技巧:Dropout、L2 正規化、Early Stopping、學習率排程,每一種都同時示範 PyTorch 與 TensorFlow/Keras 的寫法,並說明如何整合進前幾篇的 train.py。
🔎 過擬合是什麼?
想像一個學生只死背教科書上的例題,考試時遇到稍微不同的題目就完全不會。這就是過擬合——模型在訓練資料上表現很好,但對新資料(驗證集或真實世界)表現很差。
簡單來說:
- 資料增強 → 「讓模型看更多種圖片」
- 避免過擬合 → 「限制模型不要死背訓練資料」
這兩招通常會一起使用,才能讓模型真正學會「懂」而不是「背」。
🔎 如何判斷過擬合?
圖:過擬合的 Loss 曲線特徵 ─ Train Loss 持續下降、Val Loss 先降後升,代表模型開始「背答案」而非真正學會
觀察訓練過程中 Train Loss 與 Val Loss 的走勢,就能判斷模型目前的狀態:
| 現象 | 判斷 |
|---|---|
| Train Loss 下降,Val Loss 也跟著下降 | 正常,模型持續改善 |
| Train Loss 下降,Val Loss 先降後升,兩者差距越來越大 | 過擬合 |
| Train Loss 與 Val Loss 都很高且停滯 | 欠擬合,模型容量不足或訓練次數不夠 |
💡 先看 Loss 曲線,再學方法
在進入四種方法之前,先用模擬資料跑出一條過擬合的 Loss 曲線,讓你有直觀的畫面。
1 | # simulate_overfitting.py |

圖:模擬 20 個 epoch 的 Loss 曲線 ─ Train Loss 持續下降,Val Loss 在第 8 個 epoch 後開始上升,典型的過擬合模式
看完這個模式,接下來的四種方法都是為了讓 Val Loss 不再往上走。
💻 診斷:繪製 Loss 曲線
在 PyTorch 微調範例 與 TensorFlow/Keras 微調範例 的訓練迴圈裡,把每個 epoch 的 Loss 記錄下來,就能繪製真實的診斷曲線。
🔸 PyTorch
在 train.py 的訓練迴圈外初始化兩個清單,每個 epoch 結束後記錄 Loss,訓練完成後繪製曲線。
1 | # plot_loss_pytorch.py |
點擊展開 / 收合完整 train.py 程式碼
1 | # train.py(已加入 Loss 記錄與曲線繪製) |

圖:記錄每個 epoch 的 Train Loss 與 Val Loss 並繪製曲線,用於診斷過擬合現象
🔸 TensorFlow/Keras
Keras 的 model.fit 會自動回傳 history 物件,直接存有每個 epoch 的 Loss,不需要手動記錄。
1 | # plot_loss_keras.py |
點擊展開 / 收合完整 train.py(含 Loss 曲線)
1 | # train.py(Keras 版本 - 已加入 Loss 曲線記錄) |

圖:使用 Keras history 物件繪製 Train Loss 與 Val Loss 曲線,直觀呈現訓練與驗證的差距
💻 方法一:Dropout

圖:Fig 1. Dropout (取自 Tikz/Dropout)
Dropout 在訓練時隨機將一部分神經元的輸出設為 0,迫使模型不能過度依賴特定神經元,從而提升泛化能力。
白話原理:訓練時隨機關掉一些神經元,強迫模型學得更均衡,不容易死背訓練資料。
🔸 PyTorch
在 PyTorch 微調範例 的 train.py 中,分類頭原本是一個 nn.Linear。
在它之前插入 nn.Dropout 即可啟用 Dropout:
1 | # dropout_pytorch.py |
🔸 TensorFlow/Keras
在 TensorFlow/Keras 微調範例 的模型架構中,在全連接層之間插入 layers.Dropout:
1 | # dropout_keras.py |
💡 Dropout 只在訓練時啟用,推論時自動關閉。PyTorch 需呼叫
model.eval()才會正確停用;Keras 則透過training參數自動控制。
💻 方法二:L2 正規化(Weight Decay)
L2 正規化對模型的權重大小施加懲罰,避免某些權重過大,讓模型的決策更分散、不過度依賴少數特徵。
白話原理:對太大的權重進行懲罰,讓模型的權重不會過度集中。
🔸 PyTorch
在 PyTorch 微調範例 的 train.py 中,optimizer 只需加入 weight_decay 參數即可啟用:
1 | # l2_pytorch.py |
🔸 TensorFlow/Keras
在 TensorFlow/Keras 微調範例 的模型架構中,對 Dense 層加入 kernel_regularizer:
1 | # l2_keras.py |
💻 方法三:Early Stopping
Early Stopping 監控驗證集 Loss,當連續 patience 個 epoch 都沒有改善時,自動停止訓練並恢復最佳模型,避免在過擬合的方向繼續訓練。
白話原理:如果驗證集好幾個 epoch 都沒有進步,就自動停止訓練,避免繼續過擬合。
🔸 PyTorch(手動實作)
在 PyTorch 微調範例 的 train.py 訓練迴圈中,加入以下邏輯取代固定 epoch 數:
1 | # early_stopping_pytorch.py |
🔸 TensorFlow/Keras(使用 Callback)
Keras 的 EarlyStopping callback 自動處理所有邏輯,restore_best_weights=True 等同於 PyTorch 版本的「訓練結束後載入最佳模型」:
1 | # early_stopping_keras.py |
💻 方法四:學習率排程
學習率從大到小逐步衰減,讓模型在訓練後期更細緻地調整,避免 Loss 在最小值附近反覆震盪。
🔸 PyTorch
在 PyTorch 微調範例 的 train.py 中已使用 StepLR。以下展示兩種常用排程器的用法,擇一加入 train.py 即可:
1 | # lr_scheduler_pytorch.py |
1 | # lr_scheduler_plateau_pytorch.py |
🔸 TensorFlow/Keras
在 TensorFlow/Keras 微調範例 的 callbacks 清單中加入 ReduceLROnPlateau:
1 | # lr_scheduler_keras.py |
⚠️ 注意事項
- 先增加資料,再加正規化:過擬合最根本的原因是資料不足,正規化只是輔助,無法完全取代資料量。上一篇的資料增強是第一道防線,這一篇的方法是第二道。
- Dropout 比率不要太高:
0.3~0.5是常用範圍,過高(如 0.8)會讓模型難以學習,Train Loss 也降不下來。 - Early Stopping 的
patience要夠:patience太小可能在模型還沒充分訓練時就停止;太大則失去提早停止的意義。通常設 5 ~ 10。 StepLR與ReduceLROnPlateau的選擇:資料集穩定、訓練行為可預期時用StepLR;訓練曲線不穩定、需要自動調整時用ReduceLROnPlateau。scheduler.step()的位置:StepLR.step()必須在每個 epoch 結束後呼叫;ReduceLROnPlateau.step(val_loss)必須傳入驗證 Loss 才能判斷是否縮小。
📊 應用場景
- 小資料集訓練:資料量少時,過擬合幾乎必然發生,需積極搭配資料增強、Dropout 與 Weight Decay 一起使用。
- 訓練前期穩定、後期微調:
ReduceLROnPlateau讓模型在收斂後期自動降低學習率,不需手動介入調整。 - 長時間訓練監控:搭配 Matplotlib 繪製 Loss 曲線,提早發現過擬合趨勢,適時介入加入正規化技巧。
- 模型上線前的品質把關:Early Stopping + ModelCheckpoint 確保儲存的一定是驗證集最佳模型,而非最後一個 epoch 的模型。
- 競賽與生產模型:通常四種方法組合使用(資料增強 + Dropout + Weight Decay + Early Stopping)以得到最穩定的泛化效果。
🎯 結語
過擬合是深度學習訓練中最常遇到的問題之一,也是工程師最需要具備診斷與處理能力的環節。
掌握 Dropout、L2 正規化、Early Stopping 與學習率排程這四種核心技巧,搭配上一篇的資料增強,能讓模型的泛化能力大幅提升。
下一步是 GPU 加速與效能優化,讓訓練速度大幅提升。
📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。
註:以上參考了
PyTorch 官方文件 — torch.optim
TensorFlow 官方文件 — Callbacks
Deep Learning Book — Regularization
