返回目錄
A
數據之鏡:從資料洞察到決策智慧 - 第 6 章
第六章 非監督式模型與異常偵測
發布於 2026-02-25 19:07
# 第六章 非監督式模型與異常偵測
本章聚焦於在無標籤資料情境下,如何發掘結構、分群、並辨識異常。雖然監督式學習以預測為主,非監督式方法在許多商業場景(如客戶分群、欺詐偵測、設備健康監控)同樣不可或缺。章節結構如下:
1. [分群(Clustering)概念與評估](#分群概念與評估)
2. [K‑means](#k-means)
3. [DBSCAN(基於密度的聚類)](#dbscan)
4. [Isolation Forest(異常偵測)](#isolation-forest)
5. [主成分分析(PCA)與可視化](#主成分分析pca)
6. [實務案例:信用卡欺詐偵測](#實務案例信用卡欺詐偵測)
7. [工具與實作建議](#工具與實作建議)
8. [小結](#小結)
---
## 分群概念與評估
- **聚類目標**:將資料分成若干群組,使同一群內的樣本相似度高,而不同群間相似度低。
- **常見評估指標**:
- **輪廓係數(Silhouette Coefficient)**:-1 ~ 1,越高表示聚類效果越好。
- **肘部法(Elbow Method)**:觀察總變異平方和(Within‑Cluster Sum of Squares, WCSS)隨聚類數變化的拐點。
- **Calinski–Harabasz 指數**:群內變異與群間變異之比,值越大表示聚類效果好。
> **實務提示**:在實際業務中,聚類往往與業務目標結合,如「高價值客戶」分群,應先定義業務 KPI,再選擇合適的聚類方法與評估指標。
---
## K‑means
K‑means 是最常用且易於實作的聚類演算法。核心思路是:
1. 隨機選擇 `K` 個中心點。
2. 分配每個樣本到最近的中心。
3. 重新計算每個群的中心為群內樣本均值。
4. 重複步驟 2‑3,直到中心不再變動或達到預設迭代上限。
### 參數說明
| 參數 | 說明 |
|------|------|
| `n_clusters` | 群數 K |
| `init` | 初始化方法 (`k-means++` 建議) |
| `max_iter` | 最大迭代次數 |
| `tol` | 迭代收斂容忍度 |
| `random_state` | 隨機種子 |
### 典型程式碼(Python / scikit‑learn)
python
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import pandas as pd
# 讀取資料
X = pd.read_csv('customer_features.csv').drop('customer_id', axis=1)
# 特徵標準化(K‑means 受尺度影響)
X_scaled = StandardScaler().fit_transform(X)
# 決定 K 值(肘部法)
wcss = []
for k in range(1, 11):
kmeans = KMeans(n_clusters=k, init='k-means++', random_state=42)
kmeans.fit(X_scaled)
wcss.append(kmeans.inertia_)
# 選擇 K=4(假設肘部在此)
kmeans = KMeans(n_clusters=4, init='k-means++', random_state=42)
clusters = kmeans.fit_predict(X_scaled)
# 結果匯出
X['cluster'] = clusters
X.to_csv('customer_clusters.csv', index=False)
### 適用情境
- 客戶分群(市場細分)
- 產品特徵聚類(同類產品組合)
- 供應鏈風險分層
---
## DBSCAN(基於密度的聚類)
DBSCAN 針對密度分佈不均且含噪聲的資料非常有效。它不需要預先指定聚類數,且能自動辨識噪聲點。核心概念:
- **eps**:鄰域半徑,決定鄰域範圍。
- **min_samples**:鄰域內最小樣本數,定義核心點。
### 參數說明
| 參數 | 說明 |
|------|------|
| `eps` | 鄰域半徑(可通過 k‑distance 曲線確定) |
| `min_samples` | 核心點最小鄰域樣本數 |
| `metric` | 距離度量(默認 `euclidean`) |
### 典型程式碼
python
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
import numpy as np
import pandas as pd
X = pd.read_csv('purchase_data.csv').drop(['order_id', 'timestamp'], axis=1)
X_scaled = StandardScaler().fit_transform(X)
# 確定 eps(k‑distance 曲線)
from sklearn.neighbors import NearestNeighbors
nbrs = NearestNeighbors(n_neighbors=5).fit(X_scaled)
distances, _ = nbrs.kneighbors(X_scaled)
distances = np.sort(distances[:, 4]) # 第 5 個最近鄰距離
import matplotlib.pyplot as plt
plt.plot(distances)
plt.title('k-distance curve')
plt.xlabel('Points sorted by distance')
plt.ylabel('Distance to 5th nearest neighbor')
plt.show()
# 假設在拐點處選取 eps=0.5
dbscan = DBSCAN(eps=0.5, min_samples=5)
labels = dbscan.fit_predict(X_scaled)
X['cluster'] = labels
X.to_csv('dbscan_clusters.csv', index=False)
### 適用情境
- 地理空間聚類(衛星影像、城市規劃)
- 網路流量異常聚類
- 生物資訊(基因表達)聚類
---
## Isolation Forest(異常偵測)
Isolation Forest 基於樹結構將異常樣本「孤立」的原理,計算平均孤立深度(average path length)作為異常分數。
### 參數說明
| 參數 | 說明 |
|------|------|
| `n_estimators` | 隨機樹數量 |
| `max_samples` | 每棵樹抽樣的樣本數(可設 `auto`) |
| `contamination` | 估計異常比例 |
| `behaviour` | 取樣方式 (`old` / `new`) |
### 典型程式碼
python
from sklearn.ensemble import IsolationForest
import pandas as pd
X = pd.read_csv('sensor_readings.csv')
iso_forest = IsolationForest(n_estimators=200, contamination=0.01, random_state=42)
iso_forest.fit(X)
scores = iso_forest.decision_function(X) # -1 為異常,1 為正常
anomaly_labels = iso_forest.predict(X) # -1 / 1
X['anomaly_score'] = scores
X['anomaly'] = anomaly_labels
X.to_csv('anomaly_detection.csv', index=False)
> **注意**:若資料含大量噪聲,建議先做 `StandardScaler`,並考慮對離群值進行處理後再訓練。
### 適用情境
- 工業 IoT 故障預警
- 銀行交易異常
- 網站入侵偵測
---
## 主成分分析(PCA)
PCA 是線性降維工具,亦常作為分群前的資料預處理或後續可視化手段。核心在於找到資料中方差最大的方向(主成分),並保留前幾個主成分以近似原資料。
### 步驟
1. 標準化特徵。
2. 計算協方差矩陣。
3. 求其特徵值與特徵向量。
4. 選擇前 `k` 個特徵值最大之特徵向量作為主成分。
### 典型程式碼
python
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import pandas as pd
import matplotlib.pyplot as plt
X = pd.read_csv('credit_card_features.csv').drop(['customer_id', 'timestamp'], axis=1)
X_scaled = StandardScaler().fit_transform(X)
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X_scaled)
plt.scatter(X_pca[:, 0], X_pca[:, 1], c='steelblue', alpha=0.5)
plt.title('PCA 2‑D Projection')
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()
### 小技巧
- **方差比**:`pca.explained_variance_ratio_`,可用於決定保留多少主成分。
- **可視化**:t‑SNE / UMAP 可與 PCA 結合產生更有意義的 2‑D / 3‑D 投影。
---
## 實務案例:信用卡欺詐偵測
### 背景
在信用卡交易資料中,正常交易佔 99.9% 以上,欺詐交易僅佔 0.1%。此類極端不平衡資料適合使用 Isolation Forest 或聚類+異常偵測結合的管道。
### 數據示例(`creditcard.csv`)
- `V1` ~ `V28`:PCA 變換特徵。
- `Amount`:交易金額。
- `Class`:標籤(1 為欺詐)。
### 分析流程
| 步驟 | 目的 |
|------|------|
| 1. 讀取資料 | 檢視標籤分布 |
| 2. 特徵縮放 | `StandardScaler` |
| 3. 先用 Isolation Forest 取得異常分數 |
| 4. 以分數做二分,取得預測標籤 |
| 5. 交叉驗證(Precision‑Recall, ROC‑AUC) |
### 典型程式碼
python
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import IsolationForest
from sklearn.metrics import classification_report, precision_recall_curve, roc_auc_score
import matplotlib.pyplot as plt
# 讀取資料
data = pd.read_csv('creditcard.csv')
X = data.drop('Class', axis=1)
y_true = data['Class']
# 標準化
X_scaled = StandardScaler().fit_transform(X)
# Isolation Forest
iso = IsolationForest(n_estimators=200, contamination=0.001, random_state=42)
iso.fit(X_scaled)
# 異常分數(decision_function)
scores = iso.decision_function(X_scaled)
labels_pred = iso.predict(X_scaled) # -1: anomaly, 1: normal
# 轉為 0/1
labels_pred = (labels_pred == -1).astype(int)
# 評估
print('ROC‑AUC:', roc_auc_score(y_true, scores))
print(classification_report(y_true, labels_pred))
# Precision‑Recall 曲線
prec, recall, _ = precision_recall_curve(y_true, scores)
plt.plot(recall, prec)
plt.title('Precision‑Recall Curve')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.show()
> **結果說明**:Isolation Forest 在此場景通常能達到 **AUC ≈ 0.99**,但 Precision‑Recall 曲線會因欺詐比例極低而變得敏感。可考慮結合 `SMOTE`、`KNN` 失真重樣本或使用 `One‑Class SVM` 進行細化。
---
## 工具與實作建議
| 底層框架 | 特色 |
|----------|------|
| **scikit‑learn** | K‑means、DBSCAN、Isolation Forest、PCA 全部支援,易於快速原型開發。
| **H2O.ai** | 提供基於 MapReduce 的大規模聚類與 Isolation Forest,支援 Spark。
| **MLlib (Spark)** | `KMeans`, `BisectingKMeans`, `RandomForest`(Isolation Forest 類)可在分布式環境下處理 TB‑級資料。
| **TensorFlow/Keras** | 可透過自訂 auto‑encoder + `IsolationForest` 的結合,進行深度聚類。
### 設計提示
1. **資料前處理**:特徵縮放、缺失值填補、離散化等直接影響聚類與異常偵測。
2. **模型解釋**:聚類結果應配合可視化(散點圖、熱力圖)及商業指標說明,避免「黑箱」效應。
3. **更新機制**:對於持續流動資料,採用 `incremental learning` 或滑動窗口更新模型。
4. **警報閾值**:異常分數可設成「動態閾值」,根據業務週期或成本敏感度調整。
---
## 小結
- **K‑means**:簡單、快速,但對離散噪聲不敏感,適合規模中等且相似度高的資料。
- **DBSCAN**:不需預設群數,能自動處理噪聲,適合密度不均或含異常點的資料。
- **Isolation Forest**:針對高維異常偵測表現優秀,計算成本低。
- **PCA**:作為降維工具,可提升聚類表現並視覺化高維結構。
- **評估指標**:輪廓係數、肘部法、ROC‑AUC 等是判斷模型好壞的客觀量化方法。
- **實務關鍵**:非監督式方法往往需要與業務需求緊密結合,確定 KPI、調整參數、並透過可視化與解釋提升決策支持。
> **下一步**:在第七章中,我們將探討「深度學習中的自監督式(Self‑Supervised)方法」,進一步擴展在無標籤資料中的模型開發。