返回目錄
A
數據洞察:從基礎到實踐的資料科學全書 - 第 8 章
第 8 章:從模型到部署——CI/CD 與雲端實踐
發布於 2026-02-28 06:03
# 第 8 章:從模型到部署——CI/CD 與雲端實踐
> **目標**:將已完成的機器學習模型,以自動化、可重複、可追蹤的方式交付到雲端服務,並建立監控與治理機制。\
> **核心概念**:
> - MLOps:將 DevOps 原則擴展到機器學習生命周期。
> - CI(Continuous Integration)/CD(Continuous Delivery / Deployment)
> - 容器化(Docker)
> - 版本控制與模型註冊(Model Registry)
> - 監控、日誌與回滾策略
---
## 8.1 MLOps 基礎與流程概念
| 階段 | 主要工作 | 關鍵工具 |
|------|----------|----------|
| 1. 需求與設計 | 定義模型輸出、性能指標、監控目標 | Jira、Confluence |
| 2. 版本控制 | 代碼、數據、模型都需版本化 | Git、DVC |
| 3. CI | 自動化測試、模型訓練、單元測試 | GitHub Actions、GitLab CI |
| 4. CD | 構建容器、推送至註冊表、部署端點 | Docker、ECR、SageMaker |
| 5. 監控 | 指標、日誌、模型漂移 | CloudWatch、SageMaker Model Monitor |
| 6. 回滾 | 快速回復到前一版本 | Git、SageMaker Endpoint Configuration |
> **重點**:MLOps 不是單一工具,而是一組流程、文化與技術的結合。每個階段都必須有可測量的 KPI 來評估效果。
---
## 8.2 Docker 化模型:從實驗到生產
### 8.2.1 Dockerfile 範例(Python + scikit‑learn)
dockerfile
# 1️⃣ 基礎映像
FROM python:3.10-slim AS base
# 2️⃣ 設置工作目錄
WORKDIR /app
# 3️⃣ 安裝需求
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 4️⃣ 複製模型檔案
COPY model.pkl ./
# 5️⃣ 設置入口點
CMD ["python", "serve.py"]
> **說明**:
> - `requirements.txt` 只列出部署時需要的庫,避免冗餘。
> - `serve.py` 使用 Flask 或 FastAPI 建立 REST API。
### 8.2.2 `serve.py` 範例
python
from flask import Flask, request, jsonify
import joblib
import os
app = Flask(__name__)
model = joblib.load('model.pkl')
@app.route('/predict', methods=['POST'])
def predict():
data = request.json
features = [data[key] for key in sorted(data.keys())]
pred = model.predict([features])[0]
return jsonify({'prediction': pred})
if __name__ == '__main__':
host = os.getenv('HOST', '0.0.0.0')
port = int(os.getenv('PORT', 8080))
app.run(host=host, port=port)
---
## 8.3 GitHub Actions:自動化 CI/CD 流程
### 8.3.1 目錄結構
├── .github
│ └── workflows
│ └── ci_cd.yml
├── Dockerfile
├── requirements.txt
├── model.pkl
└── serve.py
### 8.3.2 `ci_cd.yml` 範例
yaml
name: CI/CD for ML Model
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
- name: Build and push image
id: build-image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags:
${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/ml-model:${{ github.sha }}
- name: Deploy to SageMaker
uses: aws-actions/aws-sam-build@v1
with:
template-file: template.yaml
> **重點**:
> - **Cache**:減少重建時間。
> - **ECR 登錄**:使用 GitHub Secrets 保障憑證安全。
> - **SageMaker 部署**:可直接使用 SAM 或 boto3 進行端點部署。
### 8.3.3 `template.yaml`(SageMaker Endpoint)
yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::SageMaker::Model
Resources:
MyModel:
Type: AWS::SageMaker::Model
Properties:
ExecutionRoleArn: arn:aws:iam::${AWS::AccountId}:role/service-role/AmazonSageMaker-ExecutionRole-20201215T000000
PrimaryContainer:
Image: ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/ml-model:${AWS::StackName}
Mode: SingleModel
ModelName: my-ml-model-${AWS::StackName}
MyEndpointConfig:
Type: AWS::SageMaker::EndpointConfig
Properties:
EndpointConfigName: my-ml-endpoint-config-${AWS::StackName}
ProductionVariants:
- VariantName: AllTraffic
ModelName: !Ref MyModel
InitialInstanceCount: 1
InstanceType: ml.m5.large
MyEndpoint:
Type: AWS::SageMaker::Endpoint
Properties:
EndpointName: my-ml-endpoint-${AWS::StackName}
EndpointConfigName: !Ref MyEndpointConfig
---
## 8.4 SageMaker 端點部署與版本管理
1. **模型註冊**:
- 使用 `sagemaker` SDK 建立模型註冊表(Model Registry)。
- 每次 CI 產生新版本,會自動寫入註冊表。
2. **端點配置**:
- `ProductionVariants` 允許同時部署多個版本,用於 A/B 測試。
3. **Canary 部署**:
- 先將 10% 的流量指向新版本,觀察指標,再逐步放大。
4. **回滾**:
- 若新版本表現不佳,直接將 `EndpointConfig` 指回上一版本即可。
### 8.4.1 Python 範例(使用 SageMaker SDK)
python
import sagemaker
from sagemaker.model import Model
from sagemaker.endpoint import EndpointConfig, Endpoint
sess = sagemaker.Session()
role = 'arn:aws:iam::123456789012:role/service-role/AmazonSageMaker-ExecutionRole-20201215T000000'
image_uri = f'{sess.boto_region_name}.dkr.ecr.{sess.boto_region_name}.amazonaws.com/ml-model:{git_sha}'
model = Model(
image_uri=image_uri,
role=role,
sagemaker_session=sess
)
# 建立端點配置
endpoint_config = EndpointConfig(
name='my-endpoint-config',
variants=[{'InstanceType': 'ml.m5.large', 'InitialInstanceCount': 1, 'ModelName': model.name}]
)
# 建立端點
endpoint = Endpoint(
name='my-ml-endpoint',
config_name=endpoint_config.name
)
---
## 8.5 監控與治理
| 監控指標 | 來源 | 目的 |
|----------|------|------|
| 延遲 (Latency) | CloudWatch Metrics | 確保 SLA 內服務回應時間 |
| 成功率 (Success Rate) | CloudWatch Metrics | 監測模型錯誤率 |
| 模型漂移 | SageMaker Model Monitor | 追蹤特徵分佈變化 |
| 日誌 (Logs) | CloudWatch Logs | 排錯與合規審計 |
| 安全審計 | GuardDuty、IAM | 防範未授權存取 |
### 8.5.1 SageMaker Model Monitor 範例
python
from sagemaker.model_monitor import DefaultModelMonitor
monitor = DefaultModelMonitor(
role=role,
instance_count=1,
instance_type='ml.m5.xlarge',
volume_size_in_gb=5,
base_directory='/opt/ml/processing/input',
output_path='s3://my-bucket/monitor-output'
)
monitor.schedule(
cron_expression='cron(0 0 * * ? *)',
processing_inputs=[{'dataSource': {'s3DataSource': {'s3Uri': 's3://my-bucket/input', 's3DataType': 'S3Prefix'}}}]
)
> **備註**:Model Monitor 需要定期檢查輸入資料與預測結果的統計,並生成報告。可透過 CloudWatch Alarm 觸發自動回滾。
---
## 8.6 實務建議與常見陷阱
| 項目 | 建議 | 常見問題 |
|------|------|----------|
| 版本命名 | 用 Git SHA 或 semantic version | 無法追蹤實際變更 |
| Secrets 管理 | 使用 GitHub Secrets、AWS Secrets Manager | 機密洩漏 |
| 測試覆蓋 | 單元測試、整合測試、A/B 測試 | 只測試成功分支 |
| 監控設定 | 設定 CloudWatch Alarm、Slack 通知 | 監控閾值不合理 |
| 資源成本 | 節省 Spot Instances、Auto Scaling | 不注意成本估算 |
> **結語**:
> 透過 Docker、GitHub Actions 與 SageMaker,您可以在短時間內從實驗階段推向生產,並確保每一次迭代都具備可追蹤、可回滾與可監控的特性。未來章節將進一步探討模型公平性與偏見偵測,確保您的部署不僅高效,也能負責任地服務社會。