聊天視窗

數據科學實戰:從問題到洞見 - 第 7 章

第7章 模型評估與可解釋性

發布於 2026-03-05 11:48

# 第7章 模型評估與可解釋性 本章聚焦於兩大核心:**模型性能評估** 與 **可解釋性(Explainability)**。透過合適的指標,我們能夠量化模型的表現;透過可解釋方法,我們能將黑盒模型轉化為可被人理解的決策工具。兩者結合,讓模型不僅準確,更能說服業務同仁、符合合規需求,並持續推進資料科學的價值。 --- ## 7.1 性能指標概覽 ### 7.1.1 回歸指標 | 指標 | 定義 | 公式 | 何時使用 | |------|------|------|----------| | **MAE** | 平均絕對誤差 | \[ \text{MAE} = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat{y}_i| \] | 數值尺度相同、對離群點不敏感 | | **MSE** | 均方誤差 | \[ \text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 \] | 離群點影響較大,需強調嚴重錯誤 | | **RMSE** | 均方根誤差 | \[ \text{RMSE} = \sqrt{\text{MSE}} \] | 與原始尺度一致,易於解釋 | | **R²** | 決定係數 | \[ R^2 = 1 - \frac{\sum (y_i-\hat{y}_i)^2}{\sum (y_i-\bar{y})^2} \] | 0~1,越接近 1 代表解釋力越高 | | **Adjusted R²** | 調整後決定係數 | \[ \bar{R}^2 = 1 - \left(1-R^2\right)\frac{n-1}{n-p-1} \] | 針對多變量模型,懲罰過度擬合 | ### 7.1.2 分類指標 | 指標 | 定義 | 公式 | 何時使用 | |------|------|------|----------| | **Accuracy** | 正確率 | \[ \frac{TP+TN}{TP+TN+FP+FN} \] | 取決於類別平衡 | | **Precision** | 精確率 | \[ \frac{TP}{TP+FP} \] | 重要在錯誤判為正例代價高時 | | **Recall** | 召回率 | \[ \frac{TP}{TP+FN} \] | 重要在漏判代價高時 | | **F1-score** | 平衡精確率與召回率 | \[ 2\times\frac{Precision\times Recall}{Precision+Recall} \] | 選擇權衡兩者 | | **AUC‑ROC** | 接收者操作特徵曲線下面積 | AUC 取值 0~1 | 兩類分離度量 | | **AUC‑PR** | 精度召回曲線下面積 | AUC 取值 0~1 | 極度不平衡時更適合 | | **Log Loss** | 交叉熵損失 | \[ -\frac{1}{n}\sum_{i=1}^{n}[y_i\log(p_i)+(1-y_i)\log(1-p_i)] \] | 需要概率輸出 | ### 7.1.3 交叉驗證 > **k‑fold CV**:將資料切成 k 份,輪流作為驗證集,其餘作為訓練集。最常見的做法是 k=5 或 k=10。計算多次評估指標的平均值與標準差,可更可靠地估計模型泛化能力。 python from sklearn.model_selection import cross_val_score, StratifiedKFold from sklearn.metrics import make_scorer, f1_score skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) f1_scorer = make_scorer(f1_score) scores = cross_val_score(rf, X, y, cv=skf, scoring=f1_scorer) print('F1 mean:', scores.mean(), 'std:', scores.std()) --- ## 7.2 混淆矩陣 混淆矩陣直觀展示模型在各類別上的表現。對於多類別,矩陣擴展為 n×n。以下為二類別示例: | | 預測正類 | 預測負類 | |---|---|---| | 真正類 | TP | FN | | 真負類 | FP | TN | > **提醒**:在不平衡資料集(例如罕見事件偵測),Accuracy 可能失真,應依賴召回率、F1、AUC 等指標。 python from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay import matplotlib.pyplot as plt cm = confusion_matrix(y_test, y_pred) disp = ConfusionMatrixDisplay(confusion_matrix=cm) disp.plot() plt.title('Confusion Matrix') plt.show() --- ## 7.3 可解釋性方法 隨著模型複雜度提升,**可解釋性** 越來越重要。以下列出常見技術,並說明其適用場景。 ### 7.3.1 全局解釋 vs 局部解釋 | 類型 | 目的 | 典型方法 | |------|------|----------| | **全局** | 解釋整體模型行為 | 變量重要性、PDP、ICE、Partial Dependence Plot | | **局部** | 解釋單一預測 | SHAP, LIME, Anchors | ### 7.3.2 SHAP (SHapley Additive exPlanations) - 基於 Shapley 值(博弈論)計算每個特徵對預測的貢獻。 - **Advantages**:一致性、可加性、可視化靈活。 - **Common Visuals**: - **Summary Plot**:所有樣本的特徵重要性分布。 - **Dependence Plot**:某特徵值與 SHAP 值之關係。 - **Force Plot**:單一預測的貢獻分解。 python import shap explainer = shap.TreeExplainer(rf) shap_values = explainer.shap_values(X_test) # Summary Plot shap.summary_plot(shap_values, X_test) # Force Plot for first instance shap.force_plot(explainer.expected_value, shap_values[0], X_test.iloc[0]) ### 7.3.3 LIME (Local Interpretable Model‑agnostic Explanations) - 以局部線性模型近似黑盒模型在某個預測附近的行為。 - **Usage**:快速得到「為何這個客戶被預測為非流失」的直觀說明。 python from lime import lime_tabular explainer = lime_tabular.LimeTabularExplainer( training_data=np.array(X_train), feature_names=X_train.columns, class_names=['Non‑Churn','Churn'], discretize_continuous=True ) exp = explainer.explain_instance(X_test.iloc[0], rf.predict_proba, num_features=5) exp.show_in_notebook(show_table=True) ### 7.3.4 Partial Dependence Plot (PDP) & ICE - PDP:觀察單一特徵改變時,模型預測的平均變化。 - ICE:每個樣本單獨的依賴曲線,可顯示個體差異。 python from sklearn.inspection import plot_partial_dependence features = ['age', 'income'] plot_partial_dependence(rf, X_test, features, kind='both') plt.show() --- ## 7.4 實例:信用卡欺詐偵測 以下示範從資料載入、模型評估到 SHAP 可視化的完整流程。 python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import roc_auc_score, f1_score, confusion_matrix import shap # 1. 載入資料 credit = pd.read_csv('creditcard.csv') X = credit.drop('Class', axis=1) y = credit['Class'] # 2. 分割資料 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, stratify=y, random_state=42 ) # 3. 模型訓練 rf = RandomForestClassifier(n_estimators=200, max_depth=12, random_state=42) rf.fit(X_train, y_train) # 4. 評估 pred = rf.predict(X_test) proba = rf.predict_proba(X_test)[:,1] print('AUC:', roc_auc_score(y_test, proba)) print('F1:', f1_score(y_test, pred)) print('Confusion Matrix:\n', confusion_matrix(y_test, pred)) # 5. SHAP 解析 explainer = shap.TreeExplainer(rf) shap_values = explainer.shap_values(X_test) shap.summary_plot(shap_values[1], X_test) > **觀察**:在信用卡欺詐問題中,**V14**、**V12** 等特徵往往表現出高 SHAP 值,表明它們對模型決策影響巨大。透過 Force Plot,可進一步說明單筆交易被判斷為欺詐的原因,方便審計與合規。 --- ## 7.5 可解釋性最佳實務 | 建議 | 為什麼重要 | |------|--------------| | **設定解釋目標** | 選擇全局或局部解釋取決於決策流程與合規要求 | | **與領域專家合作** | 專家能將數值解釋轉化為業務語言 | | **可視化簡潔** | 直觀圖表更易於決策者快速理解 | | **版本化解釋** | 隨模型迭代,保持解釋的可追溯性 | | **合規審核** | 確認解釋不暴露敏感資訊,遵守 GDPR、個資法 | | **自動化測試** | 在 CI/CD 中加入解釋性指標檢查,防止模型偏差 | --- ## 7.6 實務工具總結 | 套件 | 功能 | 範例程式碼 | |------|------|------------| | `scikit-learn` | metrics、cross_val_score、PDP | `from sklearn.metrics import f1_score` | | `shap` | 全局/局部可解釋 | `explainer = shap.TreeExplainer(rf)` | | `lime` | 局部可解釋 | `explainer = lime_tabular.LimeTabularExplainer(...)` | | `yellowbrick` | 視覺化評估 | `from yellowbrick.classifier import ROCAUC` | | `mlflow` | 實驗管理、metric logging | `mlflow.log_metric('f1', f1)` | --- ## 小結 1. **性能評估**:選擇合適的指標(回歸 vs 分類、平衡 vs 不平衡),透過交叉驗證估計泛化能力。 2. **混淆矩陣**:直觀展現錯誤類型,特別在不平衡場景下的指標解讀。 3. **可解釋性**:SHAP 與 LIME 為兩大主流方法,分別提供全局與局部說明。PDP、ICE、特徵重要性則輔助解釋。 4. **實務結合**:在 CI/CD、MLflow 之中,將評估指標與解釋輸出一同儲存,確保實驗可追溯。 5. **倫理與合規**:可解釋性不僅提升模型透明度,也是法律合規的必要步驟。 透過本章的指標與工具,讀者可以在實務專案中不僅驗證模型表現,更能向決策者、合規人員清楚說明「為什麼」模型會這樣做,進一步提升資料科學的商業價值與社會信任。