聊天視窗

數據洞察:從基礎到實踐的資料科學全書 - 第 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,您可以在短時間內從實驗階段推向生產,並確保每一次迭代都具備可追蹤、可回滾與可監控的特性。未來章節將進一步探討模型公平性與偏見偵測,確保您的部署不僅高效,也能負責任地服務社會。