====== Modul 4: Kontinuerlig integrering och driftsättning för ML ====== ===== Översikt ===== I denna modul utforskar vi tillämpningen av kontinuerlig integrering och driftsättning (CI/CD) specifikt för maskininlärningssystem. Vi kommer att lära oss hur man anpassar traditionella CI/CD-praktiker för att hantera de unika utmaningarna med ML, inklusive dataversionshantering, modellvalidering och A/B-testning. Modulen fokuserar på att bygga automatiserade arbetsflöden som säkerställer att ML-modeller kan utvecklas, testas och driftsättas på ett säkert och effektivt sätt. ===== Lärandemål ===== Efter denna modul kommer du att: * Förstå skillnaden mellan traditionell CI/CD och ML-specifik CI/CD * Kunna implementera CI/CD-pipelines för ML-projekt * Behärska modellvalidering och godkännandeprocesser * Skapa automatiserade driftsättningsstrategier för ML-modeller * Implementera A/B-testning för modeller i produktion * Hantera rollback och återställning av ML-system ===== 4.1 Introduktion till CI/CD för ML ===== ==== Traditionell CI/CD vs. ML CI/CD ==== | **Aspekt** | **Traditionell CI/CD** | **ML CI/CD** | | **Artefakter** | Kodbaserade binärer/containers | Modeller + kod + konfiguration | | **Validering** | Enhetstester, integrationstester | Datakvalitetstester, modellvalideringstester | | **Miljövariabler** | Konfiguration, endpoints | Feature stores, modellparametrar | | **Byggsteg** | Kompilering, paketisering | Träning, validering, paketisering | | **Tidsåtgång** | Minuter | Timmar till dagar (för träning) | | **Driftsättning** | Vanligtvis atomär | Kan kräva gradvis utrullning | | **Rollback** | Relativt enkel (tidigare version) | Komplex (återställ data + modell) | ==== CI/CD/CT (Continuous Training) ==== ML-system introducerar ett nytt koncept: Continuous Training (CT), som innebär automatisk omträning av modeller när: * Nya data blir tillgängliga * Modellprestanda sjunker under ett tröskelvärde * Koden för modellarkitekturen uppdateras * Feature engineering ändras ==== MLOps CI/CD-mognadsnivåer ==== * **Nivå 0**: Manuell process - ingen CI/CD * **Nivå 1**: ML-pipeline-automatisering - CI för kod, manuell CD * **Nivå 2**: CI/CD-pipeline-automatisering - automatiserad driftsättning * **Nivå 3**: Fullständig CI/CD/CT - automatiserad omträning och driftsättning ===== 4.2 Implementering av CI för ML-projekt ===== ==== Komponenter i ML CI-pipelines ==== * **Kodkvalitetskontroll**: Linting, formatering, statisk kodanalys * **Enhetstestning**: Testa individuella komponenter * **Integrationstestning**: Testa samverkan mellan komponenter * **Datakvalitetstestning**: Validera att data uppfyller förväntningar * **Lightweight modellträning**: Träna på mindre dataset för verifiering * **Modellutvärdering**: Validera modellprestanda mot baselines ==== Implementering med GitHub Actions ==== # .github/workflows/mlops-ci.yml name: MLOps CI Pipeline on: push: branches: [ main, dev ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install flake8 pytest pytest-cov if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 run: | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - name: Test with pytest run: | pytest tests/ --cov=src - name: Run data quality checks run: | python scripts/validate_data.py --data-path data/sample.csv - name: Run lightweight model training run: | python scripts/train_model.py --small-dataset --epochs 1 - name: Validate model performance run: | python scripts/evaluate_model.py --model-path models/latest.h5 --threshold 0.7 ==== Data-relaterade CI-kontroller ==== * **Dataintegritet**: Kontrollera att data uppfyller scheman och begränsningar * **Datafördelning**: Validera att datafördelningen inte har förändrats avsevärt * **Feature drift**: Kontrollera att feature-fördelningen är konsekvent * **Referensdata**: Jämför med referensdataset för att upptäcka avvikelser ==== Användning av DVC för datapipelines i CI ==== # .github/workflows/dvc-data-ci.yml name: DVC Data Pipeline CI on: push: branches: [ main ] paths: - 'data/**' - 'dvc.yaml' - 'params.yaml' jobs: data_pipeline: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install dvc dvc[s3] if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: eu-west-1 - name: Pull DVC data run: | dvc pull - name: Run DVC pipeline run: | dvc repro - name: Run data validation run: | python scripts/validate_data_pipeline.py - name: Push DVC results run: | dvc push ===== 4.3 Implementering av CD för ML-projekt ===== ==== Komponenter i ML CD-pipelines ==== * **Modellvalidering**: Grundlig utvärdering av modellprestanda * **Modelljämförelse**: Jämförelse med nuvarande produktionsmodell * **Modellåtgärdsplan**: Automatisk godkännande eller manuell granskning * **Modellpaketisering**: Förpackning av modeller för driftsättning * **Infrastrukturförberedelse**: Skapande eller uppdatering av infrastruktur * **Driftsättning**: Publicering av modellen i produktionsmiljö * **Post-driftsättningsvalidering**: Kontrollera att driftsättningen lyckades ==== Implementering med GitHub Actions och AWS ===== # .github/workflows/mlops-cd.yml name: MLOps CD Pipeline on: workflow_run: workflows: ["MLOps CI Pipeline"] branches: [main] types: [completed] jobs: deploy: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install awscli boto3 if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: eu-west-1 - name: Download model from S3 run: | aws s3 cp s3://my-model-bucket/models/latest/ ./models/latest/ --recursive - name: Validate model run: | python scripts/validate_model_for_production.py --model-path models/latest/model.h5 - name: Compare with current production model run: | python scripts/compare_models.py --new-model models/latest/model.h5 --threshold 0.05 - name: Package model as Docker image run: | docker build -t my-model-service:${{ github.sha }} . - name: Push Docker image to ECR run: | aws ecr get-login-password | docker login --username AWS --password-stdin ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-1.amazonaws.com docker tag my-model-service:${{ github.sha }} ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-1.amazonaws.com/my-model-service:${{ github.sha }} docker push ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.eu-west-1.amazonaws.com/my-model-service:${{ github.sha }} - name: Update ECS service run: | aws ecs update-service --cluster ml-cluster --service my-model-service --force-new-deployment - name: Wait for deployment run: | aws ecs wait services-stable --cluster ml-cluster --services my-model-service - name: Validate deployment run: | python scripts/validate_deployment.py --endpoint https://api.example.com/model ==== CD för gradvis utrullning av modeller ==== * **Canary releases**: Driftsättning till en liten användargrupp först * **Blue/Green-driftsättning**: Parallella miljöer för snabb växling * **Feature flagging**: Aktivera/inaktivera specifika modellversioner för olika användare ==== Exempel på gradvis utrullning med Kubernetes ==== # kubernetes/model-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: model-service spec: replicas: 10 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 selector: matchLabels: app: model-service template: metadata: labels: app: model-service spec: containers: - name: model-service image: my-model-registry/model-service:latest ports: - containerPort: 8080 readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 10 resources: limits: cpu: "1" memory: "2Gi" requests: cpu: "0.5" memory: "1Gi" ===== 4.4 A/B-testning av ML-modeller ===== ==== A/B-testning för ML ==== * **Definition**: Jämför två modellversioner i produktion för att avgöra vilken som presterar bättre * **Användningsfall**: Validera modellförbättringar, experimentera med nya algoritmer, optimera affärsmätvärden * **Key Performance Indicators (KPIs)**: Definiera tydliga framgångsmätvärden ==== Implementering av A/B-testning ==== * **Trafikuppdelning**: Ruttning av användare till olika modellversioner * **Statistisk utvärdering**: Beräkning av statistisk signifikans * **Automatisk promotion**: Främjande av den vinnande modellen ==== Exempel på A/B-testning med AWS SageMaker ==== import boto3 import json # Skapa en SageMaker-klient sagemaker_client = boto3.client('sagemaker') # Konfigurera A/B-testning response = sagemaker_client.create_endpoint_config( EndpointConfigName='my-ab-test-config', ProductionVariants=[ { 'VariantName': 'ModelA', 'ModelName': 'model-a', 'InitialInstanceCount': 1, 'InstanceType': 'ml.c5.large', 'InitialVariantWeight': 0.5 }, { 'VariantName': 'ModelB', 'ModelName': 'model-b', 'InitialInstanceCount': 1, 'InstanceType': 'ml.c5.large', 'InitialVariantWeight': 0.5 } ] ) # Skapa eller uppdatera endpoint response = sagemaker_client.create_endpoint( EndpointName='my-ab-test-endpoint', EndpointConfigName='my-ab-test-config' ) # För att anropa en specifik modellvariant för testning runtime_client = boto3.client('sagemaker-runtime') response = runtime_client.invoke_endpoint( EndpointName='my-ab-test-endpoint', ContentType='application/json', TargetVariant='ModelA', # Specifikt anropa ModelA Body=json.dumps({"features": [1, 2, 3, 4]}) ) ==== Övervakning och utvärdering av A/B-testresultat ==== * **Datainsamling**: Lagring av prediktioner och utfall för varje variant * **Mätning**: Beräkning av KPIs för varje modellvariant * **Visualisering**: Dashboards för att visa testresultat över tid * **Automatiskt beslut**: Algoritmer för att avgöra när testet kan avslutas ===== 4.5 Automationsstrategier för ML-driftsättning ===== ==== Triggers för automatisk driftsättning ==== * **Data-driven**: Trigga vid nya data eller dataförändring * **Prestanda-driven**: Trigga när modellprestanda sjunker * **Schema-driven**: Regelbunden omträning och driftsättning * **Händelse-driven**: Trigga vid specifika händelser, t.ex. kodändringar ==== Hantering av driftsättningsfrekvens ==== * **Hög frekvens**: Kontinuerlig omträning för snabbt föränderliga data * **Medelhög frekvens**: Daglig eller veckovis omträning * **Låg frekvens**: Månatlig eller kvartalsvis omträning ==== Automatiserad godkännandeprocess ==== * **Automatiskt godkännande**: För mindre modellförändringar * **Semi-automatiskt godkännande**: Automatisk validering + manuell granskning * **Manuellt godkännande**: För större modellförändringar eller känsliga system ==== Exempel på godkännandeprocess i ML-pipeline ==== def evaluate_and_approve_model(model_path, production_model_path, metrics_threshold): """Utvärd och godkänn en modell baserat på tröskelvärden""" # Ladda modellerna new_model = load_model(model_path) prod_model = load_model(production_model_path) # Utvärdera på testdata new_metrics = evaluate_model(new_model, test_data) prod_metrics = evaluate_model(prod_model, test_data) # Beräkna prestandaförbättring improvement = {} for metric_name, threshold in metrics_threshold.items(): improvement[metric_name] = new_metrics[metric_name] - prod_metrics[metric_name] # Kontrollera om alla tröskelvärden är uppfyllda approval_decision = True approval_reasons = [] for metric_name, threshold in metrics_threshold.items(): if improvement[metric_name] < threshold: approval_decision = False approval_reasons.append(f"{metric_name} förbättring {improvement[metric_name]:.4f} under tröskelvärde {threshold}") if approval_decision: approval_reasons.append("Alla prestandamätvärden möter förbättringströskelvärdena") return { "approved": approval_decision, "reasons": approval_reasons, "metrics": new_metrics, "improvement": improvement } ===== 4.6 Rollback och återhämtningsstrategier ===== ==== Utmaningar med ML-rollbacks ==== * **Komplex återställning**: Modell + infrastruktur + data * **Data dependencies**: Modeller är beroende av historiska data * **Dåliga prediktioner**: Felaktiga prediktioner kan propagera i system ==== Implementering av effektiva rollback-mekanismer ==== * **Modellversionering**: Tydlig spårning av alla driftsatta modeller * **Infrastruktur som kod**: Versionerad infrastruktur för återställning * **Observabilitet**: Tidig upptäckt av problem * **Automatisk återställning**: Självläkande system vid upptäckt av problem ==== Exempel på automatisk rollback-logik ==== def monitor_and_rollback_if_needed(deployed_model_id, performance_threshold, window_size=1000): """Övervaka modellprestanda och återställ om den faller under tröskelvärdet""" # Hämta senaste prestandamätvärden recent_metrics = get_recent_metrics(deployed_model_id, window_size) # Beräkna genomsnittlig prestanda avg_performance = np.mean([m['accuracy'] for m in recent_metrics]) if avg_performance < performance_threshold: print(f"Modellprestanda {avg_performance:.4f} under tröskelvärde {performance_threshold}") # Hämta tidigare (stabil) modellversion previous_stable_model = get_previous_stable_model() # Initiera rollback rollback_success = initiate_rollback(deployed_model_id, previous_stable_model.id) if rollback_success: print(f"Rollback till modell {previous_stable_model.id} lyckades") # Skicka notifiering till team send_alert( subject="Automatisk modellrollback utförd", message=f"Modell {deployed_model_id} återställd till {previous_stable_model.id} på grund av låg prestanda" ) else: print("Rollback misslyckades, eskalera till manuell åtgärd") # Skicka larmnotifiering för manuell åtgärd send_alert( subject="AKUT: Modellrollback misslyckades", message=f"Manuell åtgärd krävs för modell {deployed_model_id}", priority="high" ) else: print(f"Modellprestanda {avg_performance:.4f} över tröskelvärde {performance_threshold}, ingen åtgärd krävs") ===== Praktiska övningar ===== 1. **CI Pipeline**: Implementera en CI-pipeline för ett ML-projekt med GitHub Actions 2. **CD Pipeline**: Skapa en CD-pipeline för automatisk driftsättning av ML-modeller 3. **A/B-testning**: Implementera A/B-testning för två modellvarianter 4. **Rollback-strategi**: Designa och implementera en rollback-strategi för ML-modeller ===== Verktygsintroduktion ===== * **GitHub Actions**: Konfiguration för ML CI/CD * **AWS SageMaker**: Driftsättning och A/B-testning * **Kubernetes**: Gradvis utrullning av ML-modeller * **FastAPI**: REST API för modellbetjäning ===== Läsresurser ===== * "Continuous Delivery for Machine Learning" - Continuous Delivery Foundation * "Practical MLOps" - Noah Gift & Alfredo Deza * "Implementing CI/CD for ML" - AWS Technical Guide * "A/B Testing Machine Learning Models" - Microsoft Azure Documentation ===== Nyckelinsikter ===== * CI/CD för ML kräver särskild hänsyn till data och modeller utöver kod * En robust modellvalideringsprocess är avgörande före driftsättning * Gradvis utrullning och A/B-testning minskar risken för problem i produktion * Automatiserade pipeline-triggers bör anpassas efter datans och modellens natur * Effektiva rollback-strategier är avgörande för ML-systemens tillförlitlighet ===== Nästa steg ===== I nästa modul kommer vi att utforska containerisering och orkestrering av ML-applikationer, där vi kommer att lära oss hur man paketerar och driftsätter ML-modeller i containeriserade miljöer.