返回目錄
A
資料科學深度探究:從原理到實務 - 第 7 章
第七章:模型部署與持續運維
發布於 2026-02-26 11:08
# 第七章:模型部署與持續運維
## 7.1 前言
在前六章中,我們從理論到實作,完整覆蓋了強化學習的核心概念、演算法與風險倫理。此刻,模型已經完成訓練並在驗證集上表現良好,下一步就要將它「帶到實際世界」。部署與運維不僅是技術挑戰,更關乎可持續發展、可追蹤性與安全性。
本章將
1. **拆解部署流程**:從容器化到雲端服務。
2. **構建 CI/CD**:自動化測試、版本管理、回滾策略。
3. **監控與度量**:SLO、SLI、模型漂移與資料偏差。
4. **實作案例**:以 Flask+Docker+MLflow 為例,示範完整從容器構建到本地部署的流程。
5. **可重複實驗設計**:保持實驗可追蹤、可復現。
透過實務範例與工具,我們將把理論落地,確保模型在生產環境中的穩定與可信度。
---
## 7.2 什麼是模型部署?
> **部署** (Deployment) 指的是將訓練好的模型包裝成可執行單位,並在實際環境中提供預測服務。部署不等於模型上線;它還包含持續監控、版本控制、資源配置等面向。
### 7.2.1 部署的主要需求
| 需求 | 目的 |
|------|------|
| **可擴充性** | 隨負載自動調整容器數量 |
| **可追蹤性** | 追蹤模型版本、參數與依賴 |
| **高可用** | 容錯、熱備與自動回復 |
| **安全** | IAM、網路隔離、機密管理 |
| **合規性** | GDPR、HIPAA 等法規遵從 |
### 7.2.2 部署常見方式
1. **裸機/雲 VM**:直接安裝依賴,易於控制但手動維護。
2. **容器化(Docker)**:將環境打包,移植性高。
3. **容器編排(Kubernetes)**:自動擴縮、服務發現、滾動更新。
4. **伺服器無伺服器(AWS Lambda、Azure Functions)**:事件驅動、按需付費,適合輕量級模型。
5. **專用模型服務平台(TensorFlow Serving、TorchServe、ONNX Runtime)**:專為推論優化,提供 REST/GRPC 介面。
6. **雲端專門服務(SageMaker、Vertex AI、Azure ML)**:一站式訓練、部署與監控。
---
## 7.3 選擇適合的部署方案
| 案例 | 推薦方案 | 為何選擇 |
|------|----------|----------|
| **快速 MVP** | Docker + Flask + Docker Compose | 易於本地快速迭代、無需雲端依賴 |
| **高併發 Web** | Kubernetes + TF Serving | 自動擴縮、容錯、監控 |
| **輕量化邊緣** | ONNX + Edge TPU | 低延遲、低功耗 |
| **雲原生** | SageMaker / Vertex AI | 一鍵部署、模型管理、監控 |
在決策前,先評估以下指標:
- **預期流量**:低流量可用無伺服器;高流量則需要容器編排。
- **模型大小**:大型模型可考慮 GPU 支援。
- **部署頻率**:頻繁更新則需要 CI/CD 支援。
- **合規需求**:有嚴格隱私要求時選擇私有雲或本地部署。
---
## 7.4 CI/CD Pipeline:自動化部署
### 7.4.1 基本流程
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 版本控制 │───> │ 自動測試 │───> │ 自動構建 │
│ (GitHub) │ │ (pytest) │ │ (Docker) │
└─────┬───────┘ └─────┬───────┘ └─────┬───────┘
│ │ │
▼ ▼ ▼
代碼審核 報告 部署至測試環境
│ │ │
▼ ▼ ▼
合併至主分支 監控 部署至生產環境
```
### 7.4.2 典型工具
| 角色 | 工具 |
|------|------|
| **版本控制** | Git, GitHub, GitLab |
| **CI** | GitHub Actions, GitLab CI, CircleCI |
| **容器** | Docker, Docker Compose |
| **編排** | Kubernetes, Helm |
| **測試** | pytest, unittest, hypothesis |
| **監控** | Prometheus, Grafana |
| **追蹤** | MLflow, Weights & Biases |
### 7.4.3 典型 GitHub Actions 範例
```yaml
name: CI/CD Pipeline
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest tests/
- name: Build Docker image
run: docker build -t mymodel:${{ github.sha }} .
- name: Push to Docker Hub
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push mymodel:${{ github.sha }}
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v3
with:
manifests: deployment.yaml
images: mymodel:${{ github.sha }}
```
---
## 7.5 監控與度量:SLO/SLI 與 Drift
### 7.5.1 SLO/SLI 定義
- **SLO**(Service Level Objective):具體可測量的目標,例如「95% 預測延遲 < 200 ms」。
- **SLI**(Service Level Indicator):量化指標,例如「平均預測延遲」。
> **關鍵**:將 SLO 與業務目標對齊,才能確保模型的商業價值。
### 7.5.2 監控指標
| 指標 | 來源 | 目的 |
|------|------|------|
| 預測延遲 | 推論服務 | 評估性能 |
| 正確率 | 監控真實預測與實際結果 | 評估準確度 |
| 資料漂移 | 特徵分佈 | 探測環境變化 |
| 服務可用度 | 監控系統 | 評估可靠性 |
### 7.5.3 Drift 檢測方法
1. **統計檢驗**:Kolmogorov–Smirnov、Chi‑square。
2. **機器學習**:訓練監控模型判斷特徵分佈變化。
3. **閾值策略**:一旦漂移指標超過預設閾值即觸發警報或回滾。
---
## 7.6 實作案例:Flask+Docker+MLflow
以下示範如何將 `CartPole` 的簡易 DQN 模型封裝成 Flask REST API,並利用 Docker 與 MLflow 進行版本管理與部署。
### 7.6.1 目錄結構
```
├── app.py
├── Dockerfile
├── requirements.txt
├── mlruns/ # MLflow 跟蹤資料夾
├── models/
│ └── dqn_cartpole.pt
├── tests/
│ └── test_inference.py
└── deployment.yaml # Kubernetes 部署清單
```
### 7.6.2 `app.py`(Flask 推論服務)
```python
from flask import Flask, request, jsonify
import torch
import os
app = Flask(__name__)
# --------- 1. 模型載入 ---------
model_path = os.getenv("MODEL_PATH", "models/dqn_cartpole.pt")
model = torch.load(model_path)
model.eval()
# --------- 2. 推論接口 ---------
@app.route("/predict", methods=["POST"])
def predict():
data = request.get_json()
# 例子:data = {"state": [0.1, -0.2, 0.3, ...]}
state = torch.tensor(data["state"], dtype=torch.float32)
with torch.no_grad():
q_values = model(state)
action = q_values.argmax().item()
return jsonify({"action": action})
# --------- 3. 健康檢查 ---------
@app.route("/health", methods=["GET"])
def health():
return jsonify({"status": "ok"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
```
### 7.6.3 `requirements.txt`
```text
Flask==2.2.3
torch==2.0.0
mlflow==2.6.0
pytest==7.2.1
```
### 7.6.4 Dockerfile(容器化)
```dockerfile
# ① 選擇基底映像
FROM python:3.10-slim
# ② 設定工作目錄
WORKDIR /app
# ③ 複製需求並安裝
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# ④ 複製程式碼
COPY . ./
# ⑤ 指定執行入口
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_RUN_PORT=5000
CMD ["flask", "run"]
```
> **小技巧**:若模型檔案較大,可先在映像中存放 `model.pt`,再於運行時載入。
### 7.6.5 本地測試(Docker Compose)
```yaml
version: "3.8"
services:
web:
build: .
ports:
- "5000:5000"
environment:
- MODEL_PATH=models/dqn_cartpole.pt
```
執行:
```bash
docker compose up --build
```
測試推論:
```bash
curl -X POST http://localhost:5000/predict \
-H "Content-Type: application/json" \
-d '{"state": [0.1, -0.2, 0.3, 0.0, 0.5, 0.4, 0.2, -0.1]}'
```
### 7.6.6 MLflow 追蹤
1. **註冊模型**:
```python
import mlflow
mlflow.set_experiment("CartPole_DQN")
with mlflow.start_run():
mlflow.pytorch.log_model(model, "model")
mlflow.log_params({"epochs": 200, "batch_size": 32})
```
2. **部署**:將 MLflow 服務與推論服務整合,實現版本自動化。
---
## 7.7 可重複實驗設計
部署與運維的核心是「可追蹤、可復原」。以下是確保實驗可重複的關鍵步驟:
1. **使用環境變數管理所有非硬編碼參數**:
- `MODEL_PATH`
- `PORT`
- `DB_URI`
2. **將所有依賴鎖定**:`pip freeze > requirements.txt`,並在 Dockerfile 使用 `COPY requirements.txt`。
3. **將模型與資料結構打包**:使用 `torch.save`/`torch.jit.trace`,並在 MLflow 中記錄 `artifact_uri`。
4. **版本控制所有配置**:Dockerfile、Helm chart、K8s 清單、Python 依賴全部納入 Git。
5. **在 CI 里執行**:每一次 `push` 都執行 `pytest` + `docker build` + `mlflow run`,確保自動化可復原。
---
## 7.8 小結
- **部署** 是模型推論的「門面」,它涵蓋了容器化、服務編排與安全合規等多個維度。
- **CI/CD** 讓模型從訓練到上線自動化,減少人為錯誤,提升迭代速度。
- **SLO/SLI** 與 **模型漂移** 監控確保服務品質與模型可靠性,並提供可視化警報。
- **案例實作** 讓你能直接複製、測試並調整部署流程,從而將理論快速轉化為商業價值。
在接下來的章節,我們將聚焦於 **雲端大規模推論** 與 **機器學習運維平台** 的深入使用,讓你在面對實際業務需求時能迅速作出最佳決策。祝你在部署與運維的道路上順利無阻!
---
> **提示**:每一次部署前,都先在本地或 staging 環境完整跑通「測試‑構建‑部署‑測試」週期,這樣才能在正式上線時避免「部署失敗」帶來的高成本。