model-deployment について
学習済み機械学習モデルを本番環境へデプロイするためのスキルガイドです。サービング方式、コンテナ化、監視に加え、検証やロールバックの実践方法を扱います。
主な機能
- 01REST、バッチ、ストリーミング、エッジでのサービング
- 02FastAPI予測サーバーのパターン
- 03Dockerコンテナへのデプロイ
- 04ヘルスチェックと入力検証
- 05レイテンシとモデルドリフトの監視
- 06バージョン管理とロールバックの指針
活用シーン
- 01REST API経由で予測を提供
- 02大量の予測バッチを処理
- 03本番環境のレイテンシとドリフトを監視
- 04問題のあるモデルデプロイをロールバック
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill model-deploymentインストール後、Claude Code で/model-deploymentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/cicd-ml-models.mdcontainerization-deployment.mdfastapi-production-server.mdmodel-monitoring-drift.md詳細
ML モデルのデプロイ
適切なサービングとモニタリングにより、学習済みモデルを本番環境にデプロイします。
デプロイの選択肢
| 方法 | 用途 | レイテンシ |
|---|---|---|
| REST API | Web サービス | 中 |
| バッチ | 大規模処理 | 該当なし |
| ストリーミング | リアルタイム | 低 |
| エッジ | デバイス上 | 非常に低 |
FastAPI モデルサーバー
from fastapi import FastAPI
from pydantic import BaseModel
import joblib
import numpy as np
app = FastAPI()
model = joblib.load('model.pkl')
class PredictionRequest(BaseModel):
features: list[float]
class PredictionResponse(BaseModel):
prediction: float
probability: float
@app.get('/health')
def health():
return {'status': 'healthy'}
@app.post('/predict', response_model=PredictionResponse)
def predict(request: PredictionRequest):
features = np.array(request.features).reshape(1, -1)
prediction = model.predict(features)[0]
probability = model.predict_proba(features)[0].max()
return PredictionResponse(prediction=prediction, probability=probability)
Docker のデプロイ
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY model.pkl .
COPY app.py .
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
モデルのモニタリング
class ModelMonitor:
def __init__(self):
self.predictions = []
self.latencies = []
def log_prediction(self, input_data, prediction, latency):
self.predictions.append({
'input': input_data,
'prediction': prediction,
'latency': latency,
'timestamp': datetime.now()
})
def detect_drift(self, reference_distribution):
# Compare current predictions to reference
pass
デプロイのチェックリスト
- テストセットでモデルを検証済み
- API エンドポイントを文書化済み
- ヘルスチェックエンドポイントを用意済み
- 認証を設定済み
- ロギングとモニタリングを設定済み
- モデルのバージョン管理を実施済み
- ロールバック手順を文書化済み
クイックスタート:6 ステップでモデルをデプロイ
# 1. Save trained model
import joblib
joblib.dump(model, 'model.pkl')
# 2. Create FastAPI app (see references/fastapi-production-server.md)
# app.py with /predict and /health endpoints
# 3. Create Dockerfile
cat > Dockerfile << 'EOF'
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py model.pkl ./
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
EOF
# 4. Build and test locally
docker build -t model-api:v1.0.0 .
docker run -p 8000:8000 model-api:v1.0.0
# 5. Push to registry
docker tag model-api:v1.0.0 registry.example.com/model-api:v1.0.0
docker push registry.example.com/model-api:v1.0.0
# 6. Deploy to Kubernetes
kubectl apply -f deployment.yaml
kubectl rollout status deployment/model-api
既知の問題を未然に防ぐ
1. ヘルスチェックがないとダウンタイムが発生
問題:ロードバランサーが異常な Pod にトラフィックを送信し、503 エラーが発生します。
解決策:ライブネスプローブとレディネスプローブの両方を実装します。
# app.py
@app.get("/health") # Liveness: Is service alive?
async def health():
return {"status": "healthy"}
@app.get("/ready") # Readiness: Can handle traffic?
async def ready():
try:
_ = model_store.model # Verify model loaded
return {"status": "ready"}
except:
raise HTTPException(503, "Not ready")
# deployment.yaml
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 5
2. コンテナ内でモデルが見つからないエラー
問題:コンテナの起動時に FileNotFoundError: model.pkl が発生します。
解決策:Dockerfile でモデルファイルがコピーされていることと、パスが一致していることを確認します。
# ❌ Wrong: Model in wrong directory
COPY model.pkl /app/models/ # But code expects /app/model.pkl
# ✅ Correct: Consistent paths
COPY model.pkl /models/model.pkl
ENV MODEL_PATH=/models/model.pkl
# In Python:
model_path = os.getenv("MODEL_PATH", "/models/model.pkl")
3. 入力検証が未処理だと500エラーが発生
問題:無効な入力によって API が未処理の例外を発生させ、クラッシュします。
解決策:Pydantic を使用して自動検証します。
from pydantic import BaseModel, Field, validator
class PredictionRequest(BaseModel):
features: List[float] = Field(..., min_items=1, max_items=100)
@validator('features')
def validate_finite(cls, v):
if not all(np.isfinite(val) for val in v):
raise ValueError("All features must be finite")
return v
# FastAPI auto-validates and returns 422 for invalid requests
@app.post("/predict")
async def predict(request: PredictionRequest):
# Request is guaranteed valid here
pass
4. ドリフトのモニタリングがないと劣化に気付けない
問題:モデルの性能が時間とともに劣化しても、ユーザーから苦情が寄せられるまで誰も気付きません。
解決策:ドリフト検出を実装します(references/model-monitoring-drift.md を参照)。
monitor = ModelMonitor(reference_data=training_data, drift_threshold=0.1)
@app.post("/predict")
async def predict(request: PredictionRequest):
prediction = model.predict(features)
monitor.log_prediction(features, prediction, latency)
# Alert if drift detected
if monitor.should_retrain():
alert_manager.send_alert("Model drift detected - retrain recommended")
return prediction
5. リソース制限がないと OOM による強制終了が発生
問題:Kubernetes の OOMKiller によって Pod が強制終了し、サービスが停止します。
解決策:メモリと CPU の制限およびリクエストを設定します。
resources:
requests:
memory: "512Mi" # Guaranteed
cpu: "500m"
limits:
memory: "1Gi" # Max allowed
cpu: "1000m"
# Monitor actual usage:
kubectl top pods
6. ロールバック計画がないと問題のあるデプロイから戻れない
問題:新しいモデルバージョンにバグがあっても、すぐに元に戻す方法がありません。
解決策:イメージにバージョンタグを付け、前のデプロイを保持します。
# Deploy with version tag
kubectl set image deployment/model-api model-api=registry/model-api:v1.2.0
# If issues, rollback to previous
kubectl rollout undo deployment/model-api
# Or specify version
kubectl set image deployment/model-api model-api=registry/model-api:v1.1.0
7. 同期予測ではバッチ処理が遅い
問題:10,000 件の予測を1件ずつ処理すると、何時間もかかります。
解決策:バッチエンドポイントを実装します。
@app.post("/predict/batch")
async def predict_batch(request: BatchPredictionRequest):
# Process all at once (vectorized)
features = np.array(request.instances)
predictions = model.predict(features) # Much faster!
return {"predictions": predictions.tolist()}
8. CI/CD での検証がないと不良モデルをデプロイしてしまう
問題:基本的なテストに失敗するモデルをデプロイし、本番環境に支障が生じます。
解決策:CI パイプラインで検証します(references/cicd-ml-models.md を参照)。
# .github/workflows/deploy.yml
- name: Validate model performance
run: |
python scripts/validate_model.py \
--model model.pkl \
--test-data test.csv \
--min-accuracy 0.85 # Fail if below threshold
ベストプラクティス
- すべてにバージョンを付ける:モデル(セマンティックバージョニング)、Docker イメージ、デプロイ
- 継続的にモニタリングする:レイテンシ、エラー率、ドリフト、リソース使用量
- デプロイ前にテストする:ユニットテスト、統合テスト、性能ベンチマーク
- 段階的にデプロイする:カナリア(10%)の後、全体に展開
- ロールバックに備える:前のバージョンを保持し、手順を文書化
- 予測をログに記録する:デバッグとドリフト検出を可能にする
- リソース制限を設定する:OOM による強制終了とリソース競合を防止
- ヘルスチェックを使用する:適切なロードバランシングを可能にする
リファレンスを読み込むタイミング
詳細な実装を確認するには、リファレンスファイルを読み込んでください。
-
FastAPI 本番サーバー:エラーハンドリング、バリデーション(Pydantic モデル)、ロギング、ヘルスチェック/レディネスチェック、バッチ予測、モデルのバージョン管理、ミドルウェア、例外ハンドラー、パフォーマンス最適化(キャッシュ、非同期処理)を含む、本番環境ですぐに使用できる完全な FastAPI 実装については、
references/fastapi-production-server.mdを読み込んでください。 -
モデルのモニタリングとドリフト:KS 検定によるドリフト検出、Jensen-Shannon ダイバージェンス、Prometheus メトリクスとの統合、アラート設定(Slack、メール)、継続的なモニタリングサービス、ダッシュボードのエンドポイントを備えた ModelMonitor の実装については、
references/model-monitoring-drift.mdを読み込んでください。 -
コンテナ化とデプロイ:マルチステージ Dockerfile、コンテナ内でのモデルのバージョン管理、Docker Compose のセットアップ、Nginx を使用した A/B テスト、Kubernetes のデプロイ(ローリングアップデート、ブルーグリーン、カナリア)、GitHub Actions の CI/CD、デプロイのチェックリストについては、
references/containerization-deployment.mdを読み込んでください。 -
ML モデルの CI/CD:モデルの検証、データの検証、自動テスト、セキュリティスキャン、パフォーマンスベンチマーク、自動ロールバック、デプロイ戦略を含む完全な GitHub Actions パイプラインについては、
references/cicd-ml-models.mdを読み込んでください。