AI & Machine Learning Topic
Deploying ML Models
Why Model Deployment Matters
You can have the best model in the world, but if it's stuck in a Jupyter notebook, it provides zero business value. Deployment makes your work:
-
Accessible to end-users and other systems
-
Scalable to handle multiple requests
-
Reliable with proper monitoring and maintenance
-
Integratable with existing applications and workflows
Web Frameworks for Model Serving
1. Flask: The Simple & Flexible Approach
Flask is a micro web framework that's perfect for getting started quickly.
Basic Flask API Structure:
python
from flask import Flask, request, jsonify
import pickle
import pandas as pd
# Load your trained model
with open('model.pkl', 'rb') as f:
model = pickle.load(f)
app = Flask(__name__)
@app.route('/')
def home():
return {'message': 'ML Model API is running!'}
@app.route('/predict', methods=['POST'])
def predict():
# Get data from request
data = request.get_json()
# Convert to DataFrame (assuming same structure as training)
input_data = pd.DataFrame([data])
# Make prediction
prediction = model.predict(input_data)
# Return response
return jsonify({
'prediction': prediction[0],
'status': 'success'
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Running the Flask App:
bash
pip install flask python app.py
Pros: Simple, lightweight, great for prototypes
Cons: Manual setup for production, fewer built-in features
2. FastAPI: The Modern, High-Performance Approach
FastAPI is newer, faster, and designed specifically for APIs with automatic documentation.
Basic FastAPI Structure:
python
from fastapi import FastAPI
from pydantic import BaseModel
import pickle
import pandas as pd
from typing import List
# Define input data schema
class PredictionInput(BaseModel):
feature1: float
feature2: float
feature3: int
# Load model
with open('model.pkl', 'rb') as f:
model = pickle.load(f)
app = FastAPI(title="ML Model API", version="1.0")
@app.get("/")
async def root():
return {"message": "ML Model API is running!"}
@app.post("/predict")
async def predict(input_data: PredictionInput):
# Convert to dict then DataFrame
input_dict = input_data.dict()
input_df = pd.DataFrame([input_dict])
# Make prediction
prediction = model.predict(input_df)
probability = model.predict_proba(input_df).max()
return {
"prediction": int(prediction[0]),
"probability": float(probability),
"status": "success"
}
# Batch prediction endpoint
@app.post("/predict_batch")
async def predict_batch(inputs: List[PredictionInput]):
input_dicts = [item.dict() for item in inputs]
input_df = pd.DataFrame(input_dicts)
predictions = model.predict(input_df).tolist()
return {
"predictions": predictions,
"count": len(predictions)
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Running the FastAPI App:
bash
pip install fastapi uvicorn uvicorn app:app --host 0.0.0.0 --port 8000 --reload
FastAPI Advantages:
-
Automatic API documentation at
/docsand/redoc -
Type validation with Pydantic
-
Async support for better performance
-
Data serialization built-in
Model Serving Best Practices
1. Input Validation
Never trust user input! Always validate and sanitize.
python
from pydantic import BaseModel, ValidationError, validator
class HouseFeatures(BaseModel):
bedrooms: int
bathrooms: float
sqft: float
location: str
@validator('bedrooms')
def validate_bedrooms(cls, v):
if v < 0 or v > 10:
raise ValueError('Bedrooms must be between 0 and 10')
return v
@validator('sqft')
def validate_sqft(cls, v):
if v <= 0:
raise ValueError('Square footage must be positive')
return v
2. Error Handling
Gracefully handle errors and provide helpful messages.
python
from fastapi import HTTPException
@app.post("/predict")
async def predict(input_data: PredictionInput):
try:
# Your prediction logic here
result = make_prediction(input_data)
return result
except ValidationError as e:
raise HTTPException(status_code=422, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail="Internal server error")
3. Model Versioning
Keep track of different model versions.
python
MODEL_VERSION = "v1.2.0"
MODEL_ARTIFACT = f"models/random_forest_{MODEL_VERSION}.pkl"
@app.get("/model_info")
async def model_info():
return {
"version": MODEL_VERSION,
"type": "Random Forest",
"training_date": "2024-01-15"
}
4. Health Checks
Monitor your API's health.
python
@app.get("/health")
async def health_check():
# Check if model is loaded and working
try:
test_prediction = model.predict(pd.DataFrame([{
'feature1': 1.0,
'feature2': 2.0,
'feature3': 3
}]))
return {"status": "healthy", "model_loaded": True}
except Exception as e:
return {"status": "unhealthy", "error": str(e)}
Docker: Containerizing Your Application
Docker packages your application and its dependencies into a container that runs consistently anywhere.
1. Dockerfile: The Blueprint
dockerfile
# Use Python base image FROM python:3.9-slim # Set working directory WORKDIR /app # Copy requirements and install dependencies COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy application code COPY . . # Expose port EXPOSE 8000 # Command to run the application CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
2. Requirements File
txt
fastapi==0.104.1 uvicorn==0.24.0 pandas==2.0.3 scikit-learn==1.3.0 pydantic==2.5.0
3. Docker Commands
bash
# Build the Docker image docker build -t ml-api . # Run the container docker run -p 8000:8000 ml-api # Run in background (detached mode) docker run -d -p 8000:8000 --name ml-api-container ml-api # View running containers docker ps # Stop container docker stop ml-api-container
Complete Deployment Workflow
Project Structure:
text
ml-deployment/ ├── app.py ├── requirements.txt ├── Dockerfile ├── models/ │ └── model.pkl ├── tests/ │ └── test_api.py └── README.md
Testing Your API
python
# test_api.py
import requests
# Test the API
response = requests.post(
"http://localhost:8000/predict",
json={
"feature1": 5.1,
"feature2": 3.5,
"feature3": 1
}
)
print(response.json())
Using the API from Other Applications
python
import requests
def get_prediction(features):
response = requests.post(
"http://your-api-url/predict",
json=features
)
if response.status_code == 200:
return response.json()['prediction']
else:
raise Exception(f"API Error: {response.text}")
# Usage
prediction = get_prediction({
"feature1": 6.2,
"feature2": 2.8,
"feature3": 2
})
Production Considerations
1. Environment Configuration
python
import os
from dotenv import load_dotenv
load_dotenv() # Load environment variables from .env file
MODEL_PATH = os.getenv('MODEL_PATH', 'models/default_model.pkl')
API_PORT = int(os.getenv('API_PORT', 8000))
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
2. Logging
python
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
@app.post("/predict")
async def predict(input_data: PredictionInput):
logger.info(f"Received prediction request: {input_data.dict()}")
# ... prediction logic
3. Rate Limiting
python
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
@app.post("/predict")
@limiter.limit("5/minute")
async def predict(input_data: PredictionInput):
# Your prediction logic
return result
Deployment Platforms
1. Cloud Platforms:
-
AWS: EC2, ECS, Lambda, SageMaker
-
Google Cloud: Cloud Run, Compute Engine, AI Platform
-
Azure: Container Instances, App Service, Machine Learning
2. Simplified Deployment:
bash
# Heroku example heroku create my-ml-api git push heroku main # Railway example railway deploy
Key Takeaways
-
Flask is great for simplicity, FastAPI is better for performance and features
-
Always validate inputs and handle errors gracefully
-
Docker ensures consistency across different environments
-
API design matters - think about your consumers
-
Monitoring and logging are crucial for production systems
-
Start simple with a basic API, then add complexity as needed
Deployment turns your ML model from a science project into a valuable tool that can drive real business decisions and user experiences!
Comments (0)
No comments yet. Be the first to comment!