iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
自我挑戰組

用數據守護雙眼:生活型態對視力影響的探索性資料分析系列 第 21 篇

超參數調優大對決!GridSearchCV 實測隨機森林 vs. 支援向量機(SVM

  • 分享至 

  • xImage
  •  

針對 Day 20 隨機森林在高度風險類別上召回率偏低(僅 0.069)的困境,導入 5 折分層交叉驗證網格搜索(Stratified 5-Fold GridSearchCV),為隨機森林(Random Forest)尋找最佳樹深與葉節點限制;同時引入擅長在高維核空間尋找最大邊界超平面的支援向量機(Support Vector Machine, SVM with RBF Kernel),展開兩種截然不同演算法流派的性能對決。


一、為什麼引入SVM與網格調優?
在 Day 20 的隨機森林實測中,我們驗證了決策樹具備捕捉多變數特徵的能力(Sleep_Hours 與 Daily_Screen_Hours 貢獻度超 15%),但預設的樹深與分岔參數容易使模型在雜訊較大的邊界樣本上過度擬合(Overfitting),導致高度風險(High Risk)漏報嚴重。
為了解決這個瓶頸,今天的工程策略包含兩個核心主軸:

1.超參數網格搜索(GridSearchCV):

  • 不再手動盲猜參數,針對隨機森林的 max_depth(樹深限制)、min_samples_split(分裂最小樣本)、min_samples_leaf(葉節點最小樣本)進行系統化排列組合搜尋。
  • 評估指標設定為 scoring='f1_macro',強迫模型兼顧少數類的預測能力,避免模型偏向多數類的中度風險。

2.引入支援向量機(SVM with RBF Kernel):

  • SVM 藉由徑向基核函數(Radial Basis Function, RBF),將標準化後的 11 維特徵映射至無限維空間,尋求使類別間邊界間距(Margin)最大化的分離超平面。
  • 透過調整正規化參數 C(容忍錯誤懲罰度)與 gamma(單一訓練樣本影響半徑),測試幾何邊界模型能否比樹模型更好地切開交疊嚴重的眼痛與作息特徵空間。

二、撰寫雙模型 GridSearchCV 調優與對決腳本
在 Colab 中新增儲存格,使用 scikit-learn 執行雙模型調優與對比視覺化:

# ==========================================
# Day 21:GridSearchCV 超參數調優:隨機森林 vs. SVM
# ==========================================

import warnings
warnings.filterwarnings('ignore')

import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.font_manager as fm
import pandas as pd
import numpy as np

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV, StratifiedKFold
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score, f1_score

# 1. 引用中文字型
font_path = 'NotoSansTC-Regular.otf'
my_font = fm.FontProperties(fname=font_path)

# 2. 定義 5 折分層交叉驗證策略
cv_stratified = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

# --- 模型 A:隨機森林網格調優 ---
param_grid_rf = {
    'n_estimators': [100, 150],
    'max_depth': [3, 4, 5, 6],
    'min_samples_leaf': [2, 4, 6],
    'class_weight': ['balanced', None]
}

grid_rf = GridSearchCV(
    estimator=RandomForestClassifier(random_state=42),
    param_grid=param_grid_rf,
    cv=cv_stratified,
    scoring='f1_macro',
    n_jobs=-1
)
grid_rf.fit(X_train, y_train)

# --- 模型 B:支援向量機 (SVM with RBF) 網格調優 ---
param_grid_svm = {
    'C': [0.1, 1, 5, 10],
    'gamma': ['scale', 'auto', 0.01, 0.1],
    'class_weight': ['balanced', None]
}

grid_svm = GridSearchCV(
    estimator=SVC(kernel='rbf', probability=True, random_state=42),
    param_grid=param_grid_svm,
    cv=cv_stratified,
    scoring='f1_macro',
    n_jobs=-1
)
grid_svm.fit(X_train, y_train)

# 3. 測試集盲測預測
best_rf = grid_rf.best_estimator_
best_svm = grid_svm.best_estimator_

y_pred_rf_opt = best_rf.predict(X_test)
y_pred_svm_opt = best_svm.predict(X_test)

# 4. 輸出最佳參數與性能摘要表
summary_data = [
    {
        '模型名稱': '隨機森林 (優化版)',
        '最佳超參數組合': str(grid_rf.best_params_),
        '測試集準確率 (Accuracy)': f"{accuracy_score(y_test, y_pred_rf_opt)*100:.2f}%",
        'Macro F1-score': round(f1_score(y_test, y_pred_rf_opt, average='macro'), 4)
    },
    {
        '模型名稱': '支援向量機 (SVM 優化版)',
        '最佳超參數組合': str(grid_svm.best_params_),
        '測試集準確率 (Accuracy)': f"{accuracy_score(y_test, y_pred_svm_opt)*100:.2f}%",
        'Macro F1-score': round(f1_score(y_test, y_pred_svm_opt, average='macro'), 4)
    }
]

print("=== 雙模型 GridSearchCV 調優成果對決表 ===")
display(pd.DataFrame(summary_data))

# 5. 繪製 1x2 畫布:混淆矩陣橫向對比圖
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
sns.set_theme(style="white")

target_names = ['低度風險 (Low)', '中度風險 (Medium)', '高度風險 (High)']

# --- 圖 1:優化後隨機森林混淆矩陣 ---
cm_rf_opt = confusion_matrix(y_test, y_pred_rf_opt)
sns.heatmap(
    cm_rf_opt, 
    annot=True, 
    fmt='d', 
    cmap='Greens', 
    xticklabels=target_names, 
    yticklabels=target_names, 
    cbar=False, 
    ax=axes[0]
)
axes[0].set_title(f'隨機森林 (優化版) 混淆矩陣\nMacro F1: {f1_score(y_test, y_pred_rf_opt, average="macro"):.3f}', fontproperties=my_font, fontsize=13, fontweight='bold')
axes[0].set_xlabel('模型預測等級', fontproperties=my_font, fontsize=12)
axes[0].set_ylabel('真實風險等級', fontproperties=my_font, fontsize=12)
axes[0].set_xticklabels(target_names, fontproperties=my_font, fontsize=10)
axes[0].set_yticklabels(target_names, fontproperties=my_font, fontsize=10)

# --- 圖 2:優化後 SVM 混淆矩陣 ---
cm_svm_opt = confusion_matrix(y_test, y_pred_svm_opt)
sns.heatmap(
    cm_svm_opt, 
    annot=True, 
    fmt='d', 
    cmap='Purples', 
    xticklabels=target_names, 
    yticklabels=target_names, 
    cbar=False, 
    ax=axes[1]
)
axes[1].set_title(f'SVM (優化版) 混淆矩陣\nMacro F1: {f1_score(y_test, y_pred_svm_opt, average="macro"):.3f}', fontproperties=my_font, fontsize=13, fontweight='bold')
axes[1].set_xlabel('模型預測等級', fontproperties=my_font, fontsize=12)
axes[1].set_ylabel('真實風險等級', fontproperties=my_font, fontsize=12)
axes[1].set_xticklabels(target_names, fontproperties=my_font, fontsize=10)
axes[1].set_yticklabels(target_names, fontproperties=my_font, fontsize=10)

plt.tight_layout()
plt.show()

# 6. 輸出詳細分類評估報告比對
print("=== 隨機森林 (優化版) 詳細評估報告 ===")
display(pd.DataFrame(classification_report(y_test, y_pred_rf_opt, target_names=target_names, output_dict=True)).T.round(3))

print("\n=== SVM (優化版) 詳細評估報告 ===")
display(pd.DataFrame(classification_report(y_test, y_pred_svm_opt, target_names=target_names, output_dict=True)).T.round(3))

https://ithelp.ithome.com.tw/upload/images/20261005/20178794AyrcfuNkPd.png
https://ithelp.ithome.com.tw/upload/images/20261005/20178794MbRZd9ghv2.png


三、 圖表解讀與客觀數據分析
本實作以 5 折分層交叉驗證(Stratified 5-Fold CV)搭配 scoring='f1_macro' 進行超參數搜尋,對決「隨機森林(Random Forest)」與「支援向量機(SVM)」。從調優成果對決表、雙模型測試集混淆矩陣與詳細分類評估報告中,可提煉出三項關鍵的工程實證洞察:

  1. 雙模型調優勝負定調:隨機森林全面壓制 SVM

觀察測試集(100 筆樣本)的綜合評估指標,隨機森林在各項維度皆取得顯著優勢:
a.整體準確率(Accuracy):

  • 隨機森林(優化版):35.00%。
  • SVM(優化版):29.00%(落後 6.0 個百分點)。

b.宏觀平均指標(Macro Average F1-score):
隨機森林(優化版):達到 0.337,相比未調優前的 0.289 顯著提升,展現了網格搜索在三類別平衡上的調優成效。
SVM(優化版):僅 0.252,在三分類空間中呈現明顯的幾何邊界割裂。

c.實質意涵:在面對包含自覺評分、離散生活習慣與二元徵兆的混合特徵矩陣時,以條件正交切分為核心的樹狀集成演算法,其適應力遠勝於依賴高維空間超平面間距最大化的 RBF-SVM。

  1. 混淆矩陣關鍵突破:高風險召回率翻倍激增(Day 20 痛點成功破解)

對比 Day 20 隨機森林僅命中 2 筆高風險(Recall 僅 0.069)的漏報瓶頸,超參數調優展現了顯著的搶救效益:
a.高度風險(High Risk,真實 29 筆):

  • 隨機森林(優化版):成功攔截命中 7 筆(召回率由 0.069 大幅攀升至 0.241,提升超過 3.5 倍;Precision 達 0.304,F1-score 達 0.269)!
  • SVM(優化版):29 筆中僅命中 1 筆,Recall 跌落至極低的 0.034(Precision 僅 0.077,F1-score 0.048),高度風險辨識能力幾近癱瘓。

b.低度風險(Low Risk,真實 24 筆):
隨機森林命中 10 筆(Recall 0.417,F1-score 0.317)。
SVM 雖然命中 13 筆(Recall 0.542),但這是因為 SVM 發生了「偏向低度風險的單向傾斜崩塌」——SVM 將多達 22 筆中風險與 17 筆高風險皆誤判為低風險(左下角紫色深色柱),導致低風險的 Precision 僅 0.250(純屬廣義猜測拉高召回)。

  1. 最佳超參數與模型決策邊界反思

a.限制樹深(max_depth: 3)的反過度擬合價值:

  • 隨機森林的最佳參數選中了較淺的深度(max_depth: 3)與 class_weight: 'balanced'。這說明在真實生理資料中,過深的樹容易被個人主觀給分的隨機雜訊牽著走;剪枝限制為 3 層時,模型反而能專注於前三大核心分岔(睡眠時數、螢幕暴露、CESI 指數),產出泛化度更高的規則。
    b.SVM 懲罰項與幾何空間失效(C: 10):
  • SVM 選出較大的懲罰值 $C=10$ 以嘗試強行分離邊界,但由於自覺量表在 11 維空間中具有連續性與大量重疊區域,硬性最大化 Margin 反而使決策超平面劇烈偏斜,將大量邊界模糊樣本推向了邊界的某一側。

上一篇
突破線性瓶頸!隨機森林與非線性交互特徵實測
下一篇
梯度提升王牌出擊!XGBoost 多分類殘差迭代與高風險召回攻防
系列文
用數據守護雙眼:生活型態對視力影響的探索性資料分析 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言