返回目錄
A
數據科學實務:從數據蒐集到模型部署的完整流程 - 第 7 章
第7章 時序模型的可視化、異常偵測與監控
發布於 2026-02-22 20:17
# 第7章 時序模型的可視化、異常偵測與監控
本章聚焦於模型產出之後的兩大關鍵環節:**可視化** 與 **異常偵測** 以及**模型監控**。在實務上,無論是部署於生產環境還是對業務決策提供支持,僅僅有一個高性能模型已不足以確保長期價值。必須透過圖形化分析、監測指標與自動化警示,確保模型的預測準確性、可靠性與可解釋性。以下以實際範例說明整體流程,並附上可直接執行的程式碼片段與建議工具。
---
## 7.1 時序資料可視化
### 7.1.1 目標與需求
- **趨勢分析**:檢視整體走勢,確認季節性或長期變化。
- **模型預測可視化**:將實際值、訓練期預測、驗證期預測與測試期預測繪製於同一圖表,直觀比較誤差。
- **異常偵測輔助**:快速定位時間點可能的離群現象。
### 7.1.2 工具選型
| 工具 | 優點 | 缺點 |
|------|------|------|
| **Plotly Express** | 交互式、簡易 API | 需安裝 `plotly` |
| **Matplotlib + Seaborn** | 靜態圖、可嵌入報告 | 互動性較差 |
| **Bokeh** | 交互式、支援大資料 | 需要額外前端配置 |
我們選擇 **Plotly Express** 作為示範,因其既能快速生成交互式圖表,也能輕鬆嵌入 Jupyter Notebook 或 Web 服務。
### 7.1.3 範例程式
python
import pandas as pd
import plotly.express as px
from sklearn.metrics import mean_absolute_error
# 假設已經有完整的時序資料
# df 原始資料:datetime, target, feature1, ...
# df_pred_train, df_pred_val, df_pred_test 分別為各階段預測結果
# 每個 df 都有列:datetime, pred, true
def plot_predictions(df, df_train, df_val, df_test):
fig = px.line(df, x='datetime', y='true', labels={'true':'真實值'}, title='時序預測對比')
fig.add_scatter(x=df_train['datetime'], y=df_train['pred'], mode='lines', name='訓練預測')
fig.add_scatter(x=df_val['datetime'], y=df_val['pred'], mode='lines', name='驗證預測')
fig.add_scatter(x=df_test['datetime'], y=df_test['pred'], mode='lines', name='測試預測')
fig.update_layout(yaxis_title='目標變數')
fig.show()
# 範例呼叫
plot_predictions(df, df_pred_train, df_pred_val, df_pred_test)
### 7.1.4 高階可視化技巧
- **雙軸圖**:將預測誤差(MAE、RMSE)作為第二軸,觀察誤差隨時間變化。
- **熱力圖**:展示不同時間窗口內的誤差分佈,便於定位高風險區段。
- **交互式滑桿**:允許使用者在 Web 端選擇顯示時間段,提升探索體驗。
---
## 7.2 異常偵測
### 7.2.1 異常定義
- **觀測異常**:單一資料點偏離預期分布。
- **模式異常**:連續多個觀測值偏離長期模式,常見於季節性失調。
- **模型異常**:模型本身的輸出在預測區間內產生極端偏差。
### 7.2.2 方法選擇
| 方法 | 特色 | 適用場景 |
|------|------|----------|
| **基於統計的 Z-Score** | 簡單、快速 | 觀測異常,資料量大時適用 |
| **Isolation Forest** | 無監督、適合高維 | 多維特徵異常偵測 |
| **Prophet + Bayesian Anomaly Detection** | 內建季節性模型 | 時序特殊結構 |
| **LSTM Autoencoder** | 捕捉長期依賴 | 高維時序、複雜模式 |
本章以 **Isolation Forest** 與 **LSTM Autoencoder** 為例,說明如何在不同層面進行異常偵測。
### 7.2.3 Isolation Forest 範例
python
from sklearn.ensemble import IsolationForest
import numpy as np
# 假設 df_test 只包含預測值與實際值
X = df_test[['pred', 'true']].values
iso_forest = IsolationForest(contamination=0.01, random_state=42)
iso_forest.fit(X)
df_test['anomaly_score'] = iso_forest.decision_function(X)
df_test['anomaly'] = iso_forest.predict(X) # -1 表示異常
# 取出異常點
anomalies = df_test[df_test['anomaly'] == -1]
print('檢測到 {} 個異常點'.format(len(anomalies)))
### 7.2.4 LSTM Autoencoder 範例
python
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
class LSTMAutoencoder(nn.Module):
def __init__(self, input_dim, hidden_dim, seq_len):
super().__init__()
self.encoder = nn.LSTM(input_dim, hidden_dim, batch_first=True)
self.decoder = nn.LSTM(hidden_dim, input_dim, batch_first=True)
self.seq_len = seq_len
def forward(self, x):
_, (h, _) = self.encoder(x)
repeated = h.repeat(1, self.seq_len, 1)
out, _ = self.decoder(repeated)
return out
# 準備資料:seq_len=30,feature_dim=1
seq_len = 30
X_seq = []
for i in range(len(df_test)-seq_len+1):
seq = df_test['true'].values[i:i+seq_len]
X_seq.append(seq.reshape(-1,1))
X_seq = torch.tensor(X_seq, dtype=torch.float32)
dataset = TensorDataset(X_seq, X_seq)
loader = DataLoader(dataset, batch_size=64, shuffle=True)
model = LSTMAutoencoder(input_dim=1, hidden_dim=16, seq_len=seq_len)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
# 只示範 5 次 epoch
for epoch in range(5):
for xb, yb in loader:
pred = model(xb)
loss = criterion(pred, yb)
optimizer.zero_grad(); loss.backward(); optimizer.step()
訓練完畢後,對測試序列做重構,計算重構誤差。將誤差與門檻做比對,即可得到異常點。門檻可用 **百分位法** 或 **統計閾值** 決定。
### 7.2.5 實務建議
1. **多層級偵測**:觀測層級與模型層級分別設置門檻,避免單一方法誤報。
2. **門檻自動化**:利用 **Percentile(95)** 或 **RobustScaler** 讓門檻隨時間自適應。
3. **可視化整合**:將異常點在預測圖上標註,方便直覺判斷。
---
## 7.3 模型監控與持續交付
### 7.3.1 監控指標
| 指標 | 目的 |
|------|------|
| **Data Drift** | 識別輸入特徵分布變化 |
| **Concept Drift** | 識別目標變數與特徵關係變化 |
| **Prediction Drift** | 觀測預測值分布變化 |
| **Latency** | 推論時間 |
| **Error Rates** | MAE, RMSE, MAPE 之時間序列 |
| **System Metrics** | CPU, GPU 使用率、記憶體 |
### 7.3.2 工具鏈
- **MLflow**:模型管理、實驗記錄。
- **Prometheus + Grafana**:時序資料監控、告警。
- **Seldon Core / KFServing**:Kubernetes 上的模型服務。
- **KubePrometheus**:整合監控、告警、日誌。
- **TensorBoard**:可視化訓練與推論指標。
### 7.3.3 建立監控工作流程
1. **模型日誌**:每次推論回傳 `prediction`, `true_value`(若可得)與 `timestamp`。
2. **資料上傳**:將日誌寫入 Kafka / Cloud Storage,或直接寫入 Prometheus Pushgateway。
3. **Prometheus 采集**:設置 exporter 讀取模型日誌並產生 metric。
4. **Grafana Dashboard**:以 **時間滑桿** 顯示 MAE、RMSE、Prediction Drift。
5. **告警規則**:當 MAE 超過 3σ 或 Data Drift 超過 0.2 時發送 Slack / Email 通知。
6. **自動回測**:定期載入最新一週資料,使用 **A/B test** 或 **Offline Validation** 檢驗模型是否仍符合基準。
#### 範例:Prometheus Metric
python
from prometheus_client import Gauge, start_http_server
import time
# 設定指標
mae_gauge = Gauge('model_mae', 'Mean Absolute Error of the model')
latency_gauge = Gauge('model_latency_seconds', 'Inference latency')
start_http_server(8000)
while True:
# 假設我們已經有測試批次的 predictions & truths
mae = mean_absolute_error(truths, preds)
latency = compute_latency()
mae_gauge.set(mae)
latency_gauge.set(latency)
time.sleep(60)
### 7.3.4 CI/CD 與版本管理
- **模型訓練 CI**:使用 GitHub Actions 或 GitLab CI 執行 `train.py`,並將模型訓練成果儲存至 S3/Google Cloud Storage,並註冊至 MLflow Model Registry。
- **部署 CD**:當 MLflow 觸發 `new_staging_version` 時,Seldon Core 透過 Helm 升級容器,並自動替換 Kubernetes Deployment。
- **Rollbacks**:若監控告警頻繁,Kubernetes 可回滾至 `previous_version`,並透過 `kubectl rollout undo` 或 Helm 的 `history` 指令快速回退。
---
## 7.4 小結
本章從 **可視化**、**異常偵測** 到 **模型監控** 全面覆蓋了時序機器學習模型的產出評估與運營流程。關鍵點如下:
1. **結合觀測層級與模型層級** 的異常偵測,提升偵測準確度。
2. 利用 **Prometheus + Grafana** 建立實時監控面板,並設置告警觸發。
3. 以 **MLflow + Helm** 搭建 CI/CD 流程,確保模型從實驗到生產的完整鏈路。
4. **自動化門檻** 與 **自適應 drift 檢測**,確保模型在變動環境下仍具可預測性。
> **實務小提醒**:雖然時序模型難以直接得到 `true_value`,但若能透過 **監控系統** 或 **實時評估** 取得真實標籤,能大幅提升監控精度與異常修正速度。
---
## 7.5 附錄:完整的監控 & 報告示例
以下提供一個簡易的 **Streamlit** 應用,將上述可視化、異常偵測與監控統一展示:
python
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
from streamlit_echarts import st_echarts
# 讀取日誌
log_df = pd.read_csv('model_logs.csv')
# 1. 預測曲線
st.subheader('預測 vs 實際')
fig, ax = plt.subplots(figsize=(10,4))
ax.plot(log_df['timestamp'], log_df['true_value'], label='True')
ax.plot(log_df['timestamp'], log_df['prediction'], label='Pred')
ax.set_xlabel('時間')
ax.set_ylabel('目標')
ax.legend()
st.pyplot(fig)
# 2. MAE 時序
st.subheader('MAE 隨時間變化')
mae_series = log_df.groupby('date').apply(lambda g: g['true_value'].sub(g['prediction']).abs().mean())
st.line_chart(mae_series)
# 3. 異常標記
st.subheader('異常偵測結果')
st.dataframe(log_df[log_df['anomaly']==-1])
---
### 結語
透過上述可視化、異常偵測與監控流程,您將能在實際業務中快速定位模型問題,並以自動化方式進行模型回測、部署與回滾,確保模型始終保持最佳效能。
---
**後續學習**:接下來的章節將深入 **可解釋 AI (XAI)** 與 **邊緣推論優化**,進一步提升時序模型在不同環境下的可用性與效能。