返回目錄
A
資料驅動決策:從數據探索到模型部署 - 第 5 章
第 5 章 監督式模型建構
發布於 2026-02-27 16:26
# 第 5 章 監督式模型建構
本章將帶領讀者從基礎到進階,深入了解監督式學習模型的建構流程。內容涵蓋線性回歸、決策樹、隨機森林、XGBoost 等常用模型,並說明特徵工程、模型訓練、交叉驗證、超參數調優與模型選擇的完整工作流程。
## 5.1 監督式學習概念回顧
| 類別 | 目標變量 | 典型演算法 | 常見應用場景 |
|------|----------|------------|--------------|
| 回歸 | 連續數值 | 線性回歸、SVR、決策樹回歸、隨機森林回歸、XGBoost回歸 | 房價預測、銷售預測、風險評估 |
| 分類 | 離散標籤 | 邏輯回歸、KNN、決策樹、隨機森林、XGBoost、SVM | 疾病診斷、信用風險、垃圾郵件過濾 |
> **要點**:監督式學習以已標籤資料為基礎,訓練模型預測未來觀測值或分類結果。模型性能的衡量指標取決於問題類型:回歸問題使用 MAE / RMSE / R²,分類問題則使用 Accuracy / Precision / Recall / F1 / ROC‑AUC。
## 5.2 資料前處理與特徵工程
### 5.2.1 缺失值處理
- **數值特徵**:均值/中位數填補、KNN 估計
- **類別特徵**:眾數填補、常數 "Missing"
### 5.2.2 標準化與正規化
- `StandardScaler`:均值 0、標準差 1
- `MinMaxScaler`:將特徵縮放到 [0,1]
> **備註**:決策樹、隨機森林、XGBoost 對尺度不敏感,但線性模型與 SVM 對尺度敏感。
### 5.2.3 類別編碼
- `OrdinalEncoder`:有序編碼
- `OneHotEncoder` / `pd.get_dummies`:無序編碼
- `TargetEncoder` / `LeaveOneOutEncoder`:對類別變數的目標變換
### 5.2.4 特徵交互與多項式
```python
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X)
```
> **小技巧**:使用 `VarianceThreshold` 去除方差極低的特徵,可減少維度與過擬合。
## 5.3 模型建構流程
### 5.3.1 數據拆分
```python
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y) # 分類時用 stratify
```
### 5.3.2 建立 Pipeline
Pipeline 讓前處理與模型訓練串接成一個單一流程,方便交叉驗證與超參數調整。
```python
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
pipeline = Pipeline([
('scaler', StandardScaler()),
('rf', RandomForestRegressor(random_state=42))
])
```
### 5.3.3 交叉驗證
```python
from sklearn.model_selection import cross_val_score
scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
print('CV RMSE:', np.sqrt(-scores.mean()))
```
> **提示**:對於不平衡分類問題,可使用 `StratifiedKFold` 或 `RepeatedStratifiedKFold`。
## 5.4 模型專題
### 5.4.1 線性回歸
| 變數 | 說明 |
|------|------|
| `LinearRegression()` | 直接最小化 MSE,最適用於線性關係 |
| `Ridge` / `Lasso` | 加入 L2 / L1 正則化,解決多重共線性 |
| `ElasticNet` | 同時具備 L1 與 L2 的優點 |
```python
from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
```
### 5.4.2 決策樹
| 參數 | 作用 |
|------|------|
| `max_depth` | 控制樹的最大深度,防止過擬合 |
| `min_samples_split` | 分裂節點所需最小樣本數 |
| `min_samples_leaf` | 葉節點最小樣本數 |
```python
from sklearn.tree import DecisionTreeRegressor
tree = DecisionTreeRegressor(max_depth=5, random_state=42)
```
### 5.4.3 隨機森林
| 參數 | 作用 |
|------|------|
| `n_estimators` | 樹的數量,提升穩定性 |
| `max_features` | 每棵樹考慮的特徵數量 |
| `bootstrap` | 是否採用自助法抽樣 |
```python
from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor(n_estimators=200, max_features='sqrt', random_state=42)
```
### 5.4.4 XGBoost
| 參數 | 作用 |
|------|------|
| `learning_rate` | 学習率,控制每棵樹對終端模型的貢獻 |
| `n_estimators` | 基學習器數量 |
| `max_depth` | 樹深度 |
| `subsample` | 隨機子樣本比例 |
| `colsample_bytree` | 隨機特徵子集比例 |
```python
import xgboost as xgb
xgb_reg = xgb.XGBRegressor(
objective='reg:squarederror',
learning_rate=0.05,
n_estimators=500,
max_depth=6,
subsample=0.8,
colsample_bytree=0.8,
random_state=42
)
```
> **備註**:XGBoost 兼具高效與準確,對於非線性關係表現優秀,但需要較多參數調整。
## 5.5 超參數調優
### 5.5.1 GridSearchCV
```python
from sklearn.model_selection import GridSearchCV
param_grid = {
'rf__n_estimators': [100, 200, 300],
'rf__max_depth': [None, 5, 10]
}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='neg_root_mean_squared_error')
grid.fit(X_train, y_train)
print('Best params:', grid.best_params_)
```
### 5.5.2 RandomizedSearchCV
更適合大參數空間,節省計算時間。
```python
from sklearn.model_selection import RandomizedSearchCV
import scipy
param_distributions = {
'rf__n_estimators': scipy.stats.randint(100, 500),
'rf__max_depth': scipy.stats.randint(3, 15)
}
random_search = RandomizedSearchCV(pipeline, param_distributions, n_iter=50, cv=5, random_state=42)
```
## 5.6 模型評估指標
| 類別 | 指標 | 解釋 |
|------|------|------|
| 回歸 | MAE | 平均絕對誤差,對離群點不敏感 |
| 回歸 | RMSE | 平方根均方誤差,對離群點敏感 |
| 回歸 | R² | 解釋變異比例,越接近 1 越好 |
| 分類 | Accuracy | 正確分類比例 |
| 分類 | Precision | 召回率的「純度」 |
| 分類 | Recall | 抓取正例的能力 |
| 分類 | F1 | Precision 與 Recall 的調和平均 |
| 分類 | ROC‑AUC | 曲線下的面積,衡量分類器在不同閾值下的性能 |
> **實務建議**:對於不平衡資料集,Accuracy 可能誤導;此時應重視 Precision/Recall 或使用 AUC、PR‑AUC。
## 5.7 模型解釋性
| 工具 | 目的 |
|------|------|
| `feature_importances_` | 直接由樹模型提供特徵重要度 |
| SHAP | 提供局部與全局解釋,符合公平性需求 |
| LIME | 針對單一樣本提供局部解釋 |
| Partial Dependence Plots (PDP) | 視覺化特徵對預測的邊際效應 |
```python
import shap
explainer = shap.TreeExplainer(rf)
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values, X_test)
```
## 5.8 模型選擇流程
1. **基線模型**:先建立簡單模型(線性回歸、Logistic 回歸)作為基準。
2. **特徵工程**:完成缺失處理、標準化、編碼。
3. **模型比較**:使用交叉驗證同一指標比較多種模型。
4. **超參數優化**:對表現較佳的模型進行 Grid/Randomized Search。
5. **最終評估**:在測試集上評估,並做解釋性分析。
6. **部署前檢查**:確定模型可解釋、訓練時間、推論速度符合業務需求。
## 5.9 案例實作:波士頓房價預測
```python
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
# 讀取資料
boston = load_boston()
X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = pd.Series(boston.target, name='MEDV')
# 拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Pipeline
pipeline = Pipeline([
('scaler', StandardScaler()),
('rf', RandomForestRegressor(n_estimators=200, max_depth=6, random_state=42))
])
# 訓練與評估
pipeline.fit(X_train, y_train)
pred = pipeline.predict(X_test)
print('RMSE:', np.sqrt(mean_squared_error(y_test, pred)))
```
> **結論**:在此範例中,隨機森林表現優於線性回歸;若需更高精度,可嘗試 XGBoost 或提升特徵工程。
## 5.10 小結
- 監督式模型建構需要從資料前處理、特徵工程、模型選擇、超參數調優、評估指標與解釋性多個面向進行考量。
- 建議先用簡單模型建立基線,再逐步引入複雜模型與特徵交互,避免過度擬合。
- 交叉驗證與合理的評估指標能確保模型在未知資料上的穩定性。
- 解釋性工具(SHAP、LIME 等)不僅提升模型透明度,也有助於發現業務洞察。
在下一章「非監督式模型與降維」中,我們將探討 K‑means、層次聚類、PCA 等技術,協助你在無標籤資料中挖掘潛在結構。祝閱讀愉快!