AI時代系列(3) 機器學習三部曲: 🔹 第一部:《機器學習 —— AI 智慧的啟航》
51/100 第六週:模型評估與優化
51. 過擬合與欠擬合 ⚠ 過擬合像「死記」,欠擬合像「亂猜」,如何找到平衡?
過擬合與欠擬合 ⚠
過擬合像「死記」,欠擬合像「亂猜」,機器學習的關鍵就在找到平衡!
________________________________________
🔎 一、什麼是 過擬合(Overfitting)?
• 過擬合是機器學習中最常見且危險的現象之一。
• 定義:模型記住了太多訓練數據中的細節,甚至連資料中的「雜訊(Noise)」都當作重要特徵學起來了。
• 結果:在訓練集上表現極好,但一遇到沒看過的新資料,模型卻無法正確預測,失去了泛化能力。
• 生活比喻:像考試時只死背了所有範例題,但一旦題目稍微變化,就完全不會了。
✅ 過擬合現象的特徵:
• 訓練誤差(Training Error)很低
• 測試誤差(Testing Error)很高
• 模型過於複雜,決策邊界蜿蜒扭曲,硬要穿過所有點
________________________________________
🔎 二、什麼是 欠擬合(Underfitting)?
• 欠擬合是另一個極端,指模型學得太淺,連基本的資料規律都沒抓住。
• 定義:模型過於簡單,無法捕捉資料中的核心特徵或模式,導致表現不佳。
• 結果:無論訓練集還是測試集,模型都預測得很差。
• 生活比喻:像是考試前完全沒準備,看到題目只能亂猜,結果當然很慘。
✅ 欠擬合現象的特徵:
• 訓練誤差和測試誤差都很高
• 模型過於簡化,無法刻畫數據的真實規律
• 例如用一條直線去逼近一個非線性的資料集
________________________________________
🧠 三、為什麼會出現過擬合或欠擬合?
造成原因 過擬合 欠擬合
模型複雜度 過度複雜(層數多、參數多) 太簡單(模型太小、層數太少)
訓練資料量 太少,容易記住雜訊 資料量不足,無法學到規律
特徵工程 特徵太多且無篩選 特徵太少或關鍵特徵缺失
訓練次數 訓練過久,導致過度擬合 訓練不足,學習不完全
________________________________________
🎯 四、如何解決或避免?
✅ 過擬合的解法:
• 增加數據量:讓模型學習更多泛化規律
• 正則化(Regularization):
o L1 / L2 正則化,抑制權重過大
o Dropout(神經網路專用)
• 降低模型複雜度:減少層數或神經元數量
• 交叉驗證(Cross Validation):提早發現過擬合
• 提早停止(Early Stopping):在驗證集誤差開始上升時停止訓練
✅ 欠擬合的解法:
• 增加模型複雜度(加深網路、加特徵)
• 適當增加訓練輪數(Epoch)
• 選擇更強大的模型(例如從線性模型換成深度神經網路)
• 加入更多有效特徵或進行特徵工程
________________________________________
📈 五、視覺化圖解
測試誤差
▲ ____
| / \
| / \
|__________/_____________\____> 模型複雜度
欠擬合 最佳點 過擬合
✅ 左側(欠擬合):模型太簡單,無法捕捉規律
✅ 中間(最佳點):恰到好處,準確又穩健
✅ 右側(過擬合):模型過度學習,無法泛化
________________________________________
🌟 六、學習的最終目標:泛化能力(Generalization)
• 泛化能力強的模型才能「考試拿高分」
• 目標:模型不只會「背答案」,還要「舉一反三」
________________________________________
📌 總結重點口訣:
✅ 過擬合 = 背太熟,題目一變就不會
✅ 欠擬合 = 沒學好,怎麼考都不會
✅ 好模型 = 剛剛好,能抓到規律,適應新情況
________________________________________
📊 七、Python 實測:用學習曲線視覺化過擬合與欠擬合
透過 scikit-learn 的 learning_curve 工具,我們可以觀察隨著訓練樣本數增加,模型的表現如何變化,從而判斷是否過擬合或欠擬合。
📌 範例程式碼(以決策樹為例):
python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_digits
from sklearn.model_selection import ShuffleSplit
# 載入資料集
X, y = load_digits(return_X_y=True)
# 模型與學習曲線設定
estimator = DecisionTreeClassifier(max_depth=3) # 可改變 max_depth 觀察效果
cv = ShuffleSplit(n_splits=10, test_size=0.2, random_state=0)
# 計算學習曲線
train_sizes, train_scores, test_scores = learning_curve(
estimator, X, y, cv=cv, n_jobs=-1,
train_sizes=np.linspace(0.1, 1.0, 10), scoring='accuracy'
)
# 計算平均與標準差
train_scores_mean = np.mean(train_scores, axis=1)
test_scores_mean = np.mean(test_scores, axis=1)
# 畫圖
plt.figure()
plt.title("Learning Curve - Decision Tree (max_depth=3)")
plt.xlabel("Training Examples")
plt.ylabel("Accuracy")
plt.grid()
plt.plot(train_sizes, train_scores_mean, 'o-', label="Training Score")
plt.plot(train_sizes, test_scores_mean, 'o-', label="Cross-validation Score")
plt.legend(loc="best")
plt.show()
這段程式碼透過 scikit-learn 套件與手寫數字資料集 load_digits(),建構一個最大深度為 3 的決策樹分類模型,並使用 learning_curve 函數計算模型在不同訓練資料量下的學習效果,進一步繪製出「訓練分數」與「交叉驗證分數」的學習曲線,藉此觀察模型是否出現 過擬合(train高、test低) 或 欠擬合(兩者皆低) 現象;plt.show() 是整段視覺化流程的最後一行,負責真正「顯示出」這張圖,讓我們能直觀地判斷模型的泛化能力與學習狀況。
🔍 分析結果:
若訓練分數高但驗證分數低:可能過擬合(模型背熟資料但無法應對變化)
兩者皆低且差距小:表示欠擬合(模型太弱)
兩者收斂且都高:模型有良好 泛化能力