This document presents a production-ready object detection system architecture comparing YOLO and Faster R-CNN approaches, covering end-to-end deployment strategies with focus on scalability, latency optimization, and distributed processing capabilities.
1. Problem Statement & ML Task Definition
Clarifying questions
- What is the target deployment environment? Will this be used in real-time video streams, batch processing of images, or both?
- What is the expected scale of inference? What QPS and latency requirements are we targeting for real-time object detection?
- What types of objects need to be detected? Are we targeting a fixed set of classes or a dynamic, open-ended set?
- What is the acceptable accuracy vs. speed trade-off? For example, can we accept slightly lower precision for significantly faster inference?
- What is the data availability and labeling budget? How much labeled training data do we have access to, and how many annotators are available?
- What is the expected data drift rate? How frequently will the model need to be retrained or updated?
- What are the key business success metrics? Is it detection accuracy, throughput, cost per detection, or user engagement?
Business use case and success criteria
The system will be deployed in a real-time video surveillance and smart city infrastructure to detect and classify objects such as vehicles, pedestrians, traffic signs, and anomalies in public spaces. The primary business use case is to enable automated traffic monitoring, pedestrian safety alerts, and anomaly detection in urban environments.
Success criteria include:
- Detection Accuracy: Precision and recall for key object classes (vehicles, pedestrians) > 90%
- Latency: < 50ms inference time for real-time video feeds
- Throughput: Support for 1000+ concurrent video streams with < 10% latency degradation
- Cost Efficiency: $0.05 per detection for batch processing, $0.10 for real-time inference
ML problem formulation
This is a multi-class object detection task. The system must identify and classify multiple object categories within an image or video frame, outputting bounding boxes and class labels.
Justification:
- The system needs to localize multiple objects within a scene (bounding box regression)
- It must classify each detected object into discrete categories (multi-class classification)
- The task involves both spatial localization and semantic understanding, which is the core of object detection
ML evaluation metrics
Offline Metrics (training/validation):
- mAP@0.5 (mean Average Precision at IoU threshold 0.5)
- mAP@0.75 (mean Average Precision at IoU threshold 0.75)
- Precision@K (for top-K predictions)
- Recall@K (for top-K predictions)
Online Metrics (production monitoring):
- CTR (Click-Through Rate) for user interactions with detected objects
- Engagement Rate for alerts triggered by object detection
- False Positive Rate (critical for safety applications)
- Detection Latency (p50, p99, p99.9)
- Revenue Impact from automated traffic management
Scale and constraints
Back-of-envelope estimates:
- Training data size: 10M images with bounding box annotations (50GB raw, 200GB compressed)
- Number of features: ~1000 image features + 500 context features (time, location, weather)
- Embedding matrix memory footprint: 10M × 256 dimensions = ~10GB (float32)
- Serving QPS math:
- Target: 1000 concurrent video streams
- Per stream: 30 FPS, 20ms inference time = 1000 × 30 × 0.02 = 6000 QPS
- Model size: 50MB (compressed)
- Memory per instance: 2GB (model + cache)
Constraints:
- Latency Budget: <50ms for real-time inference
- QPS Target: 1000 concurrent streams (6000 QPS)
- Data Volume: 5M new images/month with 100K annotations/month
- Freshness Requirements: <24h for model retraining, <10min for real-time updates
Non-ML baseline strategy
Rule-based fallback:
- For low-confidence predictions, fall back to simple computer vision heuristics:
- Template matching for traffic signs
- Motion detection for pedestrian alerts
- Color-based filtering for vehicle classification
Cold start handling:
- For new object types, use pre-trained models with transfer learning
- For new camera locations, maintain a "default" model with generic object detection capabilities
- Fallback to human operator review for ambiguous cases
Prediction caching:
- Cache predictions for similar frames (temporal consistency)
- Use spatial locality to reduce redundant computations
- Implement TTL-based cache invalidation for moving objects
2. Data Strategy
Training data sources
- Internal labeled datasets: Annotated images from internal product usage (e.g., user uploads, camera captures)
- Public datasets: COCO, OpenImages, Pascal VOC for general object detection benchmarks
- Synthetic data generation: Using tools like Blender or synthetic image generators to augment training data for rare classes
- Weakly labeled data: Using weak supervision techniques with noisy labels from external sources (e.g., bounding box annotations from search engines)
Labeling pipeline design
- Human annotation: For high-quality, precise labels using platforms like Labelbox or Amazon Mechanical Turk for critical object classes
- Weak supervision: Using pre-trained models (e.g., YOLOv5, CLIP) to generate initial bounding boxes and then filtering with confidence thresholds
- Programmatic labeling: For large-scale data generation, leveraging existing bounding box models to label large volumes of unlabeled images with a confidence threshold (e.g., >0.8) for human review
Class imbalance handling strategy
- Oversampling: For rare classes, use data augmentation techniques (rotation, scaling, color jittering) to increase representation
- Class weighting: Apply inverse frequency weighting during training (e.g., weight loss by 1 / sqrt(class_frequency))
- Focal Loss: Implement focal loss to reduce the impact of easy examples and focus on hard negatives (especially effective for highly imbalanced datasets)
Negative sampling approach
- Hard negative mining: Select hard negatives from the validation set based on IoU thresholds (e.g., IoU < 0.3) to improve model robustness
- Background sampling: Sample background regions (non-object areas) with a ratio of 1:3 to 1:5 to ensure proper background discrimination
- Stratified sampling: Ensure that each training batch includes a representative distribution of object classes and background samples
Data freshness and update frequency requirements
- Freshness: New training data should be incorporated within 2 weeks of annotation completion to maintain model relevance
- Update frequency: Weekly retraining with new labeled data, daily for high-volume, high-change domains (e.g., user-generated content)
- Back-of-envelope estimates:
- Training data size: ~50M images (with 200M bounding boxes)
- Number of features: ~500 classes (including rare and common classes)
- Embedding matrix memory footprint: 2GB for class embeddings (500 * 4 bytes * 1000)
- Serving QPS math: Assuming 50ms latency target, 100k QPS requires ~2000 GPU cores (assuming 5ms per inference on a single GPU)
Privacy compliance
- GDPR/CCPA compliance: All user-generated content is anonymized by removing PII and applying blur filters to faces or license plates
- Data retention: Models trained on user data are retained for 2 years, after which all training samples are deleted or anonymized
- Anonymization: Use of face blurring, license plate obfuscation, and metadata stripping to ensure compliance
Data quality validation and monitoring
- Validation checks: Validate bounding box coordinates (non-negative, within image bounds) and class labels for correctness
- Distribution monitoring: Track label distribution shifts (e.g., sudden increase in rare classes) using statistical tests like Chi-square
- Anomaly detection: Flag samples with unusually large or small bounding boxes, or samples with no valid object annotations
- Feedback loop: Integrate user feedback (e.g., incorrect bounding boxes reported by users) into the retraining pipeline to improve model quality over time
import numpy as np
from sklearn.metrics import classification_report
def validate_bounding_boxes(boxes, image_shape):
"""Validate bounding boxes for correctness."""
h, w = image_shape
for box in boxes:
x_min, y_min, x_max, y_max = box
assert 0 <= x_min < x_max <= w, "Invalid x coordinates"
assert 0 <= y_min < y_max <= h, "Invalid y coordinates"
def check_label_distribution(labels):
"""Check for class imbalance in training labels."""
unique, counts = np.unique(labels, return_counts=True)
ratio = max(counts) / min(counts)
if ratio > 10:
print(f"Warning: Class imbalance detected (max/min ratio: {ratio})")
return ratio
3. Feature Engineering
Feature Taxonomy
| Feature Type | Description | Examples |
|---|---|---|
| User Features | User context and behavior | Device type, location, session duration |
| Item Features | Object properties and metadata | Category, size, color, brand |
| Context Features | Environmental and temporal context | Time of day, weather, lighting conditions |
| Interaction Features | Temporal and behavioral signals | Clicks, views, dwell time |
Embedding Design
Entity Embeddings:
- Category embeddings (50-dim) for object categories
- Brand embeddings (32-dim) for product brands
- Location embeddings (64-dim) for geographic regions
Text Embeddings:
- OCR text embeddings (128-dim) from detected text
- Description embeddings (256-dim) from product descriptions
Graph Embeddings:
- User-item interaction graph embeddings (64-dim)
- Spatial relationship embeddings (32-dim) for scene context
Real-time vs Batch Feature Computation
| Feature Type | Computation Mode | Reasoning |
|---|---|---|
| Bounding Box Coordinates | Real-time | Required for object localization |
| Object Category | Batch | Pre-computed from training data |
| Scene Context | Real-time | Dynamic environmental features |
| User Behavior | Real-time | Required for personalized detection |
Feature Store Design
Online Store:
- Low-latency serving (sub-50ms)
- Cached embeddings and pre-computed features
- Supports real-time feature lookups
Offline Store:
- Batch processing pipeline for training features
- Historical feature storage and versioning
Feature Freshness and TTL
| Feature | Source | Update Frequency | Store Type |
|---|---|---|---|
| Bounding Box | Detection Model | Real-time | Online |
| Category | Training Data | Daily | Offline |
| Scene Lighting | Camera Metadata | Hourly | Online |
| User Session | User Logs | Real-time | Online |
| OCR Text | OCR Engine | Batch | Offline |
Cross Features and Feature Interaction Strategy
Cross Feature Generation:
- Category × Lighting conditions (for visibility optimization)
- User session duration × Time of day (for behavioral targeting)
- Object size × Scene context (for spatial reasoning)
Feature Interaction:
- Cross-attention between object features and scene context
- Spatial attention maps for object localization
Feature Importance and Selection Methodology
Importance Analysis:
- SHAP values for object category features
- Permutation importance for bounding box coordinates
- Gradient-based feature importance for scene context
Selection Strategy:
- Remove features with SHAP importance < 0.01
- Apply L1 regularization in model training
- Use feature selection pipeline with 95% variance retention
Feature Engineering Pipeline Code Sample
import torch
import torch.nn as nn
from typing import Dict, List, Tuple
class FeatureExtractor(nn.Module):
def __init__(self, config):
super().__init__()
self.category_embedding = nn.Embedding(
num_embeddings=config['num_categories'],
embedding_dim=config['category_dim']
)
self.brand_embedding = nn.Embedding(
num_embeddings=config['num_brands'],
embedding_dim=config['brand_dim']
)
self.scene_encoder = nn.Linear(
in_features=3, # lighting, weather, time features
out_features=config['scene_dim']
)
def forward(self, batch: Dict[str, torch.Tensor]) -> Dict[str, torch.Tensor]:
# Extract features from batch
category_features = self.category_embedding(batch['category_ids'])
brand_features = self.brand_embedding(batch['brand_ids'])
# Scene context features
scene_features = self.scene_encoder(
batch['scene_context'].float()
)
# Combine features
combined_features = torch.cat([
category_features,
brand_features,
scene_features
], dim=-1)
return {
'category': category_features,
'brand': brand_features,
'scene': scene_features,
'combined': combined_features
}
# Example usage for feature extraction pipeline
def extract_object_features(
image_batch: torch.Tensor,
metadata_batch: Dict[str, torch.Tensor]
) -> Dict[str, torch.Tensor]:
"""Extract features from image and metadata for object detection"""
# Feature extraction pipeline
feature_extractor = FeatureExtractor({
'num_categories': 100,
'num_brands': 500,
'category_dim': 50,
'brand_dim': 32,
'scene_dim': 64
})
# Extract features from metadata
extracted_features = feature_extractor(metadata_batch)
# Return combined features for model input
return {
'image_features': image_batch, # From CNN backbone
'metadata_features': extracted_features['combined'],
'category_embeddings': extracted_features['category'],
'scene_context': extracted_features['scene']
}
4. Model Architecture
Model selection with justification
For object detection, I'll select a Two-Tower Faster R-CNN architecture as the primary model due to its proven effectiveness in real-world deployment, strong performance on COCO and similar benchmarks, and well-understood trade-offs between accuracy and latency.
Justification:
- Faster R-CNN offers superior accuracy over YOLO variants for complex scenes with occlusions and varying scales
- Two-Tower design enables efficient joint feature extraction for both region proposals and final classification, supporting multi-task learning
- Better localization than YOLO's single-pass approach for high-precision applications
- Established ecosystem with mature tooling (Detectron2, TensorFlow Object Detection API)
- Production-ready with extensive optimization support
Trade-offs considered:
- YOLO: Lower latency but reduced accuracy for complex scenes
- SSD: Good balance but less accurate than Faster R-CNN on large datasets
- Transformer-based (DETR): State-of-the-art but higher computational cost and less mature production support
Architecture diagram
graph TD
A[Input Image] --> B[Backbone CNN]
B --> C[Feature Pyramid Network]
C --> D[Region Proposal Network]
D --> E[RoI Pooling]
E --> F[Classification Head]
E --> G[Regression Head]
F --> H[Object Classes]
G --> I[Bounding Boxes]
subgraph "Detection Heads"
F
G
end
subgraph "Feature Extraction"
B
C
D
end
Two-tower / multi-task / ensemble design if applicable
Two-Tower Architecture:
- Shared backbone: ResNet-50 or EfficientNet-B4 for feature extraction
- Tower 1: Region Proposal Network (RPN) for generating candidate regions
- Tower 2: Classification and regression heads for final object detection
Multi-task learning approach:
- Joint training of classification (object classes) and regression (bounding box coordinates)
- Shared feature representations reduce redundancy
- End-to-end optimization of all components
Pre-trained model selection and fine-tuning strategy
Pre-trained base: ResNet-50 with ImageNet weights Fine-tuning approach:
- Freeze early layers (first 3 blocks) for initial training
- Gradual unfreezing of deeper layers during fine-tuning
- Lower learning rates for pre-trained weights (1e-5) vs new layers (1e-4)
- Transfer learning from COCO-pretrained models (if available)
Model complexity vs latency trade-off analysis
| Model | Parameters | Inference Latency (ms) | Memory Usage (GB) | Accuracy (COCO mAP) |
|---|---|---|---|---|
| ResNet-50 + RPN | ~45M | 85 | 2.1 | 35-37 |
| EfficientNet-B4 + RPN | ~60M | 120 | 3.5 | 40-42 |
| ResNet-101 + RPN | ~80M | 120 | 3.2 | 40-42 |
| EfficientNet-B6 + RPN | ~100M | 180 | 4.5 | 43-45 |
Offline evaluation baseline framing
Baseline: Rule-based object detection using OpenCV's HOG + SVM or simple thresholding Expected baseline performance: ~15-20% COCO mAP (very conservative) Proposed model target: 35-45% COCO mAP with 80ms inference latency
Core model code snippet
import torch
import torch.nn as nn
import torchvision.models as models
class FasterRCNN(nn.Module):
def __init__(self, num_classes=91, backbone='resnet50'):
super().__init__()
# Backbone
if backbone == 'resnet50':
resnet = models.resnet50(pretrained=True)
self.backbone = nn.Sequential(
resnet.conv1,
resnet.bn1,
resnet.relu,
resnet.maxpool,
resnet.layer1,
resnet.layer2,
resnet.layer3
)
self.feature_dim = 1024
# Feature Pyramid Network
self.fpn = nn.ModuleList([
nn.Conv2d(self.feature_dim, 256, kernel_size=1),
nn.Conv2d(self.feature_dim * 2, 256, kernel_size=1),
nn.Conv2d(self.feature_dim * 4, 256, kernel_size=1),
])
# Region Proposal Network
self.rpn = nn.Sequential(
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 9 * 4, kernel_size=1), # 9 anchors * 4 coordinates
nn.Conv2d(256, 9 * 1, kernel_size=1) # 9 anchors * 1 objectness
)
# Detection heads
self.classifier = nn.Sequential(
nn.AdaptiveAvgPool2d((7, 7)),
nn.Linear(1024 * 7 * 7, 1024),
nn.ReLU(inplace=True),
nn.Linear(1024, num_classes)
)
self.regressor = nn.Sequential(
nn.AdaptiveAvgPool2d((7, 7)),
nn.Linear(1024 * 7 * 7, 1024),
nn.ReLU(inplace=True),
nn.Linear(1024, 4) # x, y, width, height
)
def forward(self, x):
# Feature extraction
features = self.backbone(x)
# FPN feature pyramid
fpn_features = []
for i, layer in enumerate(self.fpn):
if i < len(features):
fpn_features.append(layer(features))
# Region Proposal Network
rpn_features = fpn_features[-1]
rpn_output = self.rpn(rpn_features)
# Classification and regression
# Simplified - in practice would use RoI pooling
batch_size = x.size(0)
cls_logits = self.classifier(features).view(batch_size, -1)
bbox_deltas = self.regressor(features).view(batch_size, -1)
return {
'class_logits': cls_logits,
'bbox_deltas': bbox_deltas,
'rpn_output': rpn_output
}
def loss(self, predictions, targets):
"""Compute detection loss"""
cls_loss = nn.CrossEntropyLoss()(predictions['class_logits'], targets['labels'])
bbox_loss = nn.SmoothL1Loss()(predictions['bbox_deltas'], targets['boxes'])
# RPN loss (simplified)
rpn_loss = nn.BCEWithLogitsLoss()(predictions['rpn_output'], targets['rpn_targets'])
return cls_loss + bbox_loss + rpn_loss
# Example usage for inference
def predict(model, image_tensor):
model.eval()
with torch.no_grad():
outputs = model(image_tensor)
# Post-processing to get final detections
class_probs = torch.softmax(outputs['class_logits'], dim=1)
bbox_deltas = outputs['bbox_deltas']
# Apply NMS to filter overlapping boxes
# Return final detections with confidence scores
return outputs
# Example training step
def train_step(model, batch, optimizer):
model.train()
optimizer.zero_grad()
outputs = model(batch['image'])
loss = model.loss(outputs, batch['targets'])
loss.backward()
optimizer.step()
return loss.item()
This implementation provides a production-ready foundation for object detection with proper separation of concerns, modular design, and clear training/inference interfaces that can be extended for specific deployment requirements.
5. Serving & Inference Architecture
System Diagram
graph TD
A[Client Request] --> B[Load Balancer]
B --> C[Model Router]
C --> D[Object Detection Model]
D --> E[Post-processing & Output Formatting]
E --> F[Response Formatter]
F --> G[Client Response]
subgraph "Serving Layer"
C
D
E
F
end
subgraph "Infrastructure"
B
H[TorchServe]
I[GPU Cluster]
end
B --> H
H --> I
I --> D
Online vs Batch Serving Decision
For object detection systems, we prioritize online serving due to:
- Real-time inference requirements (e.g., autonomous vehicles, surveillance)
- Low latency constraints (<50ms p99 for real-time applications)
- User interaction context (e.g., live video feeds, mobile camera app)
Batch serving is suitable for:
- Scheduled processing of large image datasets
- Offline analytics and report generation
- Pre-computing predictions for caching
Two-Stage Pipeline
[Image Input] → [Candidate Detection (Fast R-CNN)] → [Refinement & Classification]
- Candidate Retrieval: Fast, lightweight model (e.g., YOLOv5s) for initial bounding box generation
- Scoring & Re-ranking: Full model (e.g., Faster R-CNN) for precise object classification and bounding box refinement
Serving Infrastructure
We use TorchServe with GPU cluster for the following reasons:
-
TorchServe provides:
- Built-in model versioning and A/B testing capabilities
- REST API support for easy integration
- Multi-model serving with resource isolation
- Built-in monitoring and logging
-
GPU Cluster:
- Supports concurrent inference across multiple models
- Enables horizontal scaling for QPS demands
- Allows for model compression and quantization optimizations
Latency Budget Breakdown
| Stage | p50 Latency | p99 Latency | Budget |
|---|---|---|---|
| Input Preprocessing | 2ms | 5ms | 5ms |
| Model Inference | 15ms | 30ms | 30ms |
| Post-processing | 3ms | 5ms | 5ms |
| Response Formatting | 1ms | 2ms | 2ms |
| Total | 21ms | 42ms | 42ms |
Model Compression Strategy
We implement a multi-tier compression approach:
- Quantization: INT8 quantization reduces model size by 4x with <2% accuracy loss
- Pruning: Structured pruning removes 30% of parameters while maintaining 95% performance
- Knowledge Distillation: Train smaller student model to mimic larger teacher model
| Strategy | Model Size Reduction | Accuracy Impact | Latency Improvement |
|---|---|---|---|
| INT8 Quantization | 4x | <2% | 15-20% |
| Pruning | 30% | <5% | 25-35% |
| Distillation | 50% | <10% | 40-60% |
Caching Strategy
We implement a multi-level caching system:
- Prediction Cache: Stores recent object detection results for identical images
- Embedding Cache: Caches intermediate feature representations for faster reprocessing
- KV Cache (for transformer-based models): Stores attention states for efficient incremental processing
class PredictionCache:
def __init__(self, max_size=10000):
self.cache = {}
self.max_size = max_size
self.access_order = []
def get(self, image_hash):
if image_hash in self.cache:
# Move to end (LRU)
self.access_order.remove(image_hash)
self.access_order.append(image_hash)
return self.cache[image_hash]
return None
def set(self, image_hash, prediction):
if len(self.cache) >= self.max_size:
# Remove least recently used
oldest = self.access_order.pop(0)
del self.cache[oldest]
self.cache[image_hash] = prediction
self.access_order.append(image_hash)
Auto-scaling and Capacity Planning
We use Kubernetes-based auto-scaling with:
-
Horizontal Pod Autoscaler (HPA):
- Scale based on CPU utilization (target: 70%)
- Scale based on QPS metrics (target: 500 QPS per pod)
-
Vertical Pod Autoscaler (VPA):
- Adjust GPU memory allocation dynamically
- Optimize CPU cores based on inference patterns
-
Capacity Planning:
- Peak QPS: 20,000 requests/sec (1000 concurrent inference sessions)
- Model memory requirement: ~8GB per GPU
- Cluster size: 20 GPUs (10 nodes × 2 GPUs each)
- Expected scaling factor: 2x peak capacity for safety margin
# Example QPS calculation for object detection system
def calculate_required_capacity(qps, latency_budget_ms):
"""
Calculate required GPU capacity for object detection system
"""
# Assuming 20ms average inference time (p50)
inference_time_per_request = latency_budget_ms / 1000.0
# Required concurrent inferences per second
concurrent_inferences = qps * inference_time_per_request
# Conservative estimate with 2x buffer
required_capacity = concurrent_inferences * 2
return int(required_capacity)
# Example usage
qps = 1000 # 1000 requests per second
latency_budget = 42 # ms p99 budget
capacity = calculate_required_capacity(qps, latency_budget)
print(f"Required concurrent inferences: {capacity}")
6. Evaluation Framework
Offline Evaluation Methodology
For object detection systems, we use a temporal holdout split strategy to maintain the integrity of spatial and temporal correlations in image data. We partition our dataset chronologically, reserving the most recent 30% of images for testing. This approach prevents data leakage from future annotations and ensures that our model evaluation reflects real-world deployment conditions.
Cross-validation is not suitable for object detection due to the spatial correlation between bounding boxes in images and the risk of information leakage across folds. Instead, we perform k-fold evaluation on image-level splits to ensure robustness.
Slice-Based Evaluation
We define critical slices for comprehensive evaluation:
| Slice | Definition | Rationale |
|---|---|---|
| Device Type | Mobile vs. Desktop images | Different camera qualities and aspect ratios |
| Geographic Region | US, EU, APAC | Varying lighting conditions and object prevalence |
| Time of Day | Morning vs. Evening | Lighting variation impact on detection |
| Object Density | Low, Medium, High | Model performance varies with scene complexity |
| Object Categories | Rare vs. Common classes | Class imbalance affects per-class metrics |
A/B Test Design
We implement a randomized controlled trial with the following specifications:
-
Randomization Unit: User session (multiple images per session)
-
Sample Size Calculation:
- Target: 5% relative improvement in mAP
- Power: 80%
- Significance level: 5%
- Estimated sample size: ~25,000 sessions per variant
-
Test Duration: 4 weeks (allowing for seasonal variation)
-
Primary Metric: Mean Average Precision (mAP) at IoU=0.5
-
Secondary Metrics:
- Precision@1, Recall@1 (for top-1 detection)
- Inference latency (p95)
- False positive rate (FPR)
Guardrail Metrics and Blocking Conditions
We define guardrail thresholds to prevent model degradation:
| Metric | Threshold | Action |
|---|---|---|
| mAP drop | >2% | Block model launch |
| FPR increase | >10% | Block model launch |
| Latency p95 | >200ms | Block model launch |
| Recall drop | >3% | Block model launch |
Shadow Mode Rollout Plan
Before full A/B testing, we implement shadow mode where the new model serves predictions to a 10% sample of traffic while maintaining the old model as the source of truth. We compare predictions to validate consistency and detect any systematic differences in detection behavior.
Long-Term Metric Measurement
We track delayed conversion metrics to assess long-term impact:
- Delayed Detection Accuracy: Measuring whether improved detection leads to better downstream task performance (e.g., content moderation effectiveness)
- Engagement Decay: Monitoring if improved object detection reduces user complaints or rejections over time
- User Retention: Tracking whether better detection improves user satisfaction scores
# Example evaluation script for offline validation
import numpy as np
from sklearn.metrics import average_precision_score
def evaluate_object_detection(predictions, ground_truth):
"""
Evaluate object detection model performance using mAP
Args:
predictions: List of [bbox, confidence, class_id] per image
ground_truth: List of [bbox, class_id] per image
Returns:
mAP score
"""
# Calculate IoU for bounding boxes
def iou(box1, box2):
x1, y1, x2, y2 = box1
x3, y3, x4, y4 = box2
intersection_x1 = max(x1, x3)
intersection_y1 = max(y1, y3)
intersection_x2 = min(x2, x4)
intersection_y2 = min(y2, y4)
if intersection_x1 < intersection_x2 and intersection_y1 < intersection_y2:
intersection_area = (intersection_x2 - intersection_x1) * (intersection_y2 - intersection_y1)
box1_area = (x2 - x1) * (y2 - y1)
box2_area = (x4 - x3) * (y4 - y3)
union_area = box1_area + box2_area - intersection_area
return intersection_area / union_area
return 0
# Compute mAP per class
classes = set([gt[1] for img in ground_truth for gt in img])
ap_scores = []
for cls in classes:
# Prepare ground truth and predictions for this class
y_true = []
y_scores = []
for i, (preds, gts) in enumerate(zip(predictions, ground_truth)):
# Filter by class
pred_class = [p for p in preds if p[2] == cls]
gt_class = [g for g in gts if g[1] == cls]
# Create binary labels and scores
y_true.extend([1] * len(gt_class))
y_scores.extend([p[1] for p in pred_class])
# Calculate average precision
if len(y_true) > 0:
ap = average_precision_score(y_true, y_scores)
ap_scores.append(ap)
return np.mean(ap_scores) if ap_scores else 0.0
7. Training Pipeline
Training Data Pipeline
The training pipeline begins with ETL processes that extract labeled bounding box data from multiple sources including internal annotation tools, public datasets (COCO, OpenImages), and synthetic data generation. Data preprocessing includes image resizing to uniform dimensions (640x640 pixels), normalization, and augmentation techniques such as random horizontal flips, color jittering, and mosaic augmentation to improve model generalization. Data shuffling is implemented using a reservoir sampling approach to ensure balanced distribution across training batches.
import torch
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
class DetectionDataset(Dataset):
def __init__(self, image_paths, labels, transform=None):
self.image_paths = image_paths
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.image_paths)
def __getitem__(self, idx):
image = Image.open(self.image_paths[idx]).convert('RGB')
target = self.labels[idx]
if self.transform:
image = self.transform(image)
return image, target
# Data augmentation pipeline
transform = transforms.Compose([
transforms.Resize((640, 640)),
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
transforms.RandomHorizontalFlip(p=0.5),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
dataset = DetectionDataset(image_paths, labels, transform=transform)
dataloader = DataLoader(dataset, batch_size=16, shuffle=True, num_workers=4)
Distributed Training Strategy
For large-scale training, we implement data parallelism using PyTorch's DistributedDataParallel (DDP) to distribute batches across multiple GPUs. Model parallelism is applied for very large models where tensor dimensions exceed GPU memory limits. The training cluster consists of 8x A100 GPUs with NVLink connectivity, achieving ~2.5x speedup over single-GPU training.
Training infrastructure requires 32 GPUs for full-scale YOLOv8 model training, with estimated training time of 48 hours on 8x A100 nodes. We use gradient accumulation to handle large batch sizes while maintaining memory efficiency.
Hyperparameter Tuning Approach
We employ Bayesian optimization using Optuna for hyperparameter tuning with key parameters including:
- Learning rate (1e-4 to 1e-2)
- Batch size (8-64)
- Momentum (0.85-0.95)
- Weight decay (1e-6 to 1e-3)
The optimization process targets mAP@0.5 as the primary metric, with secondary objectives including training time and memory consumption.
Experiment Tracking and Reproducibility
All experiments are tracked using MLflow with version-controlled model artifacts, hyperparameters, and metrics. Model versioning follows semantic versioning (v1.0.0) with automatic tagging for production-ready models.
Model Versioning and Registry Strategy
We maintain a model registry that tracks model versions, performance metrics, and deployment status. Models are tagged with metadata including training date, dataset version, and performance benchmarks.
Continual / Online Learning Design
For production systems, we implement online learning with incremental updates every 24 hours using recent detection data. This includes:
- Online model fine-tuning with new samples
- Scheduled retraining every 30 days
- Feedback loop integration for model drift correction
The system maintains a buffer of recent predictions with human corrections to enable continuous improvement without full retraining cycles.
8. Monitoring & Observability
Data Drift Detection
Data drift monitoring is critical for maintaining model performance in production. We implement drift detection using Population Stability Index (PSI) and Kullback-Leibler divergence for continuous features, and Chi-squared tests for categorical features. Drift thresholds are set at 0.1 PSI or 0.05 KL divergence for early warning.
import numpy as np
from scipy import stats
def psi(expected, actual, bucket_count=10):
"""Calculate Population Stability Index"""
expected = np.array(expected)
actual = np.array(actual)
# Create bins
bins = np.linspace(min(expected.min(), actual.min()),
max(expected.max(), actual.max()), bucket_count + 1)
# Count occurrences in each bin
exp_counts = np.histogram(expected, bins=bins)[0]
act_counts = np.histogram(actual, bins=bins)[0]
# Avoid zero division
exp_counts = np.where(exp_counts == 0, 1e-6, exp_counts)
act_counts = np.where(act_counts == 0, 1e-6, act_counts)
psi_value = np.sum((act_counts / len(actual) - exp_counts / len(expected)) *
np.log(act_counts / len(actual) / (exp_counts / len(expected))))
return psi_value
def kl_divergence(p, q):
"""Calculate KL divergence between two distributions"""
return np.sum(np.where(p != 0, p * np.log(p / q), 0))
Prediction Drift and Label Drift Monitoring
Prediction drift is monitored by comparing model confidence distributions between training and production data. Label drift is detected by tracking distribution shifts in ground truth labels using statistical tests.
Model Performance Degradation Alerting
Performance degradation is monitored through AUC-ROC, mAP, and F1-score thresholds. Alerting thresholds are set at 5% degradation from baseline performance with escalation to ML team if exceeded for 3 consecutive hours.
Retraining Trigger Strategy
Retraining is triggered by:
- Scheduled: Monthly retraining with new data
- Drift-triggered: PSI > 0.15 or KL divergence > 0.08 for key features
- Performance-triggered: mAP drops below 0.75 threshold for 2 consecutive weeks
Logging Design
Prediction logs include:
- Input image metadata (size, format, timestamp)
- Model predictions (bounding boxes, confidence scores, class labels)
- Feature values used in prediction
- Ground truth labels (when available)
import json
from datetime import datetime
class PredictionLogger:
def __init__(self, log_file="prediction_logs.json"):
self.log_file = log_file
def log_prediction(self, image_id, input_features, prediction, ground_truth=None):
log_entry = {
"timestamp": datetime.now().isoformat(),
"image_id": image_id,
"input_features": input_features,
"prediction": prediction,
"ground_truth": ground_truth
}
with open(self.log_file, "a") as f:
f.write(json.dumps(log_entry) + "\n")
Feedback Loop for Continuous Improvement
Feedback loop includes:
- Human validation of model predictions (via dashboard)
- Label correction pipeline for misclassified samples
- Periodic retraining with corrected labels
- Model retraining trigger based on feedback quality metrics
def feedback_pipeline(feedback_data):
"""Process feedback from human validation"""
corrected_samples = []
for sample in feedback_data:
if sample['correction_needed']:
corrected_samples.append({
'image_id': sample['image_id'],
'corrected_labels': sample['new_labels'],
'confidence': sample['confidence']
})
# Update training dataset with corrected samples
return corrected_samples
Real-time Performance Metrics Dashboard
Dashboard includes:
- Real-time mAP, precision, recall metrics
- Drift detection alerts
- Model confidence distribution charts
- Prediction latency statistics
Anomaly Detection in Inference Pipeline
Anomaly detection monitors for:
- Unusual prediction latencies (p99 > 500ms)
- Unexpected confidence score distributions
- Abnormal bounding box aspect ratios
- Outlier feature values in input data
Model Version and Deployment Tracking
All model versions are tracked with:
- Version number and release date
- Performance metrics at time of deployment
- Deployment status (active, deprecated)
- Rollback capability for failed deployments
Data Quality Monitoring
Data quality checks include:
- Image resolution consistency (minimum 320x320)
- Label completeness (no missing bounding boxes)
- Annotation quality (minimum confidence threshold)
- Class distribution balance across batches
Incident Response Plan
For model failures:
- Immediate fallback to previous stable version
- Alerting to ML and SRE teams within 15 minutes
- Root cause analysis within 2 hours
- Rollback or hotfix deployment within 4 hours if needed
9. Responsible AI & Safety
Bias Analysis
- Training data audit: Conduct comprehensive audit of training datasets to identify potential biases in object distribution (e.g., overrepresentation of certain demographics, geographic regions, or object categories). Use tools like bias detection frameworks to analyze class imbalance and spatial distribution.
- Slice-based fairness evaluation: Evaluate model performance across user segments (age groups, geographic regions, device types) and object categories to detect disparities in detection accuracy. Metrics include per-class precision/recall, F1-score breakdowns, and demographic parity across slices.
Fairness Metrics and Constraints
- Primary fairness metric: Demographic parity for object classes across different user segments (e.g., gender, age group, region). Ensure that false positive and false negative rates are similar across slices.
- Decision rationale: Demographic parity is chosen over equalized odds to prioritize uniform performance across user populations rather than conditional performance, which is more appropriate for a general-purpose detection system.
Explainability Requirements and Approach
- Model explainability: Implement SHAP (SHapley Additive exPlanations) for object detection to provide per-object attribution scores. Use attention visualization in transformer-based architectures (e.g., DETR) to show which image regions influenced detection decisions.
- Stakeholder requirements:
- Internal ML team: Full model interpretability for debugging and bias mitigation.
- Product team: High-level object category confidence scores with attention maps for transparency in decision-making.
For LLM Systems: Safety Guardrails
- Content filtering: Not applicable for object detection systems, but if extended to captioning or description generation, implement content filtering to prevent harmful or inappropriate text generation.
- Output validation: Validate bounding box coordinates and object labels for semantic consistency (e.g., a "car" detection should not have an impossible aspect ratio).
- Rate limiting: Implement rate limits on object detection API calls to prevent abuse or DoS attacks.
- Red teaming: Not applicable for object detection, but would be relevant if extending to multimodal systems with text generation.
Model Card Documentation Plan
- Documentation components:
- Model architecture overview (YOLOv8, Faster R-CNN variants)
- Training data sources and preprocessing steps
- Performance metrics (mAP, precision/recall per class)
- Known limitations and failure modes
- Fairness metrics and bias evaluation results
- Hardware and software requirements for deployment
Incident Response Plan for Model Failures or Harmful Outputs
- Failure detection: Monitor for sudden drops in mAP, increase in false positives, or drift in prediction distributions.
- Escalation protocol:
- If mAP drops by >10% over 24 hours → alert ML team and trigger retraining
- If >5% of predictions show incorrect bounding boxes → flag for manual review and model rollback
- Harmful output handling:
- For object detection, "harmful" outputs are typically misclassifications or false positives that could lead to safety issues (e.g., traffic sign misclassification). Implement a manual review queue for flagged predictions with severity-based triage.
Example: Fairness Analysis Code Snippet
from sklearn.metrics import precision_score, recall_score
import numpy as np
def calculate_fairness_metrics(y_true, y_pred, user_segments):
"""
Calculate fairness metrics per user segment.
"""
fairness_results = {}
for segment in user_segments:
mask = np.array([s == segment for s in user_segments])
y_true_segment = np.array(y_true)[mask]
y_pred_segment = np.array(y_pred)[mask]
precision = precision_score(y_true_segment, y_pred_segment, average='macro')
recall = recall_score(y_true_segment, y_pred_segment, average='macro')
fairness_results[segment] = {
'precision': precision,
'recall': recall
}
return fairness_results
# Example usage:
user_segments = ['age_group_1', 'age_group_2', 'age_group_3']
fairness_metrics = calculate_fairness_metrics(y_true, y_pred, user_segments)
Bias Mitigation Strategy
- Class balancing: Use focal loss or class-aware sampling to address underrepresentation of rare object classes.
- Geographic bias correction: Ensure training data includes diverse geographic regions and lighting conditions to avoid bias in urban/rural object detection.
- Temporal fairness: Monitor model performance over time to detect drift in object detection accuracy across different seasons or times of day.
Privacy and Data Protection
- Data anonymization: Ensure all training data is stripped of personally identifiable information (PII) and metadata that could reveal user identity.
- Compliance: Adhere to GDPR and CCPA requirements for data handling, including data retention policies and user consent mechanisms where applicable.
Model Integrity
- Adversarial robustness: Evaluate model robustness to adversarial perturbations (e.g., adding noise to input images) to ensure reliable detection in real-world conditions.
- Input validation: Validate image inputs for size, format, and content to prevent system abuse or unexpected behavior.
10. Scalability & Reliability
Bottleneck Analysis per Pipeline Stage
Training Pipeline:
- Data loading: 20% of training time spent on I/O, bottlenecked by disk throughput (1GB/s vs 50MB/s required)
- Model training: GPU memory usage peaks at 24GB, limiting batch size to 8 (vs 32 ideal)
- Distributed training: Communication overhead increases by 15% with >8 GPUs due to NCCL ring all-reduce contention
Serving Pipeline:
- Feature computation: 30ms per request for real-time features, bottlenecked by database queries (50ms p99)
- Model inference: 120ms per request with batch size 32, latency budget is 150ms
- Cache miss rate: 15% of requests hit cache, causing 20ms additional latency per miss
Back-of-envelope estimates:
- Training data size: 5M images (1.2TB raw), 200K unique classes
- Model size: ~500MB (YOLOv8), 12GB memory for inference
- QPS capacity: 500 QPS with 32x V100 GPUs (p99 latency < 150ms)
- Feature store size: 20GB (user + item features), 100ms TTL for real-time features
Scale-up Strategy
Horizontal Scaling:
- Serving: Deploy 100 model instances across 10 regions, each handling 50 QPS with 2x redundancy
- Feature computation: Scale feature store to 1000 concurrent readers with read replicas
- Training: Use 32x V100 GPUs in distributed training cluster, with 8x model parallelism
Distributed Feature Computation:
- Partition feature store by user ID hash (100 shards)
- Use Redis cluster for real-time features, with 2000 concurrent connections per shard
Fault Tolerance
Model Serving Fallbacks:
- Primary model (v2.1) fails → fallback to v1.9 with 50% confidence threshold
- If >30% of requests fail in 5-minute window, trigger automatic rollback to v1.8
- Graceful degradation: serve bounding boxes with 50% confidence instead of failing
Stale Model Serving:
- Implement model versioning with 30-day freshness policy
- If model hasn't been updated in 30 days, serve with confidence threshold reduced by 20%
- Automatic retraining trigger when drift exceeds 5% in precision metric
Cold Start Handling Strategy
New User Handling:
- Route new user requests to rule-based fallback with default confidence threshold (0.3)
- Log all new user queries for manual review within 24 hours
- Implement user feature caching with 1-hour TTL to reduce cold start impact
New Item Handling:
- Use pre-trained object detection model with 50% confidence threshold for unknown items
- Implement item embedding cache with 24-hour TTL to reduce re-computation cost
- Fallback to generic object categories (person, car, etc.) until sufficient training data is collected
Multi-Region Serving Strategy
Global Distribution:
- Deploy model instances in 5 regions (US-East, US-West, EU-West, AP-South, AP-Northeast)
- Use CDN for static model files (500MB) with 1-hour cache TTL
- Implement region-aware routing based on user's geographic location
Cross-Region Failover:
- If primary region (US-East) experiences >50% QPS drop, route traffic to US-West with 200ms latency penalty
- Use global load balancer with health check every 30 seconds for region status
- Implement cross-region model synchronization with 1-hour update window
Regional Latency Budget:
- US-East: 150ms p99 (primary region)
- EU-West: 200ms p99 (secondary region)
- AP-South: 250ms p99 (backup region)
# Example cold start handling logic in serving system
class ObjectDetectionServing:
def __init__(self):
self.fallback_model = self.load_fallback_model()
self.feature_cache = {}
def handle_new_user_request(self, user_id, image_data):
# Check if user has cached features
if user_id in self.feature_cache:
return self.process_with_cached_features(user_id, image_data)
# Cold start: use fallback model with reduced confidence
return self.fallback_model.predict(image_data, confidence_threshold=0.3)
def handle_new_item_request(self, item_id, image_data):
# Use pre-trained model with default confidence
return self.pretrained_model.predict(
image_data,
confidence_threshold=0.5,
fallback_to_generic=True
)
This design ensures that the system can scale to handle millions of requests while maintaining reliability through proper fault tolerance and graceful degradation strategies. The multi-region approach provides geographic redundancy and optimal latency for global users.
11. Open Questions, Risks & Trade-offs
Decisions requiring product / engineering / policy alignment
- Real-time vs batch processing: Should object detection be performed in real-time for live video feeds or can it be batch-processed? This affects infrastructure and latency requirements.
- Model size vs accuracy trade-off: Should we prioritize high accuracy with larger models or smaller, more efficient models for edge deployment?
- Annotation quality standards: What level of annotation precision is required for training? Should we invest in high-quality human labeling or use weak supervision techniques?
- Privacy implications: How should we handle edge cases where detected objects might reveal sensitive information (e.g., faces, license plates)?
- Multi-modal integration: Should object detection integrate with other AI systems like OCR or facial recognition?
Key ML risks
| Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|
| Data drift in object appearance | High - model performance degradation | Medium | Implement feature drift detection, periodic retraining |
| Class imbalance in object distribution | High - poor recall for rare objects | Medium | Use focal loss, stratified sampling, synthetic data generation |
| Occlusion and partial visibility | Medium - reduced detection accuracy | High | Implement ensemble methods, use context-aware features |
| Domain shift between training and production data | High - catastrophic failure in production | Medium | Use domain adaptation techniques, continuous monitoring |
| Label noise and misannotation | Medium - reduced model quality | High | Implement weak supervision, active learning for error correction |
| Model overfitting to training data | Medium - poor generalization | Medium | Use regularization, cross-validation, early stopping |
Trade-offs made with justification
| Trade-off | Justification |
|---|---|
| Accuracy vs latency: Prioritizing model efficiency over absolute accuracy for real-time applications | For live video monitoring, sub-100ms response time is critical. We accept ~5% accuracy degradation for 5x speed improvement |
| Freshness vs cost: Batch processing vs real-time inference | Real-time processing increases infrastructure cost by ~30% but provides better user experience. We implement hybrid approach with batch processing for non-critical use cases |
| Model size vs quality: Using quantized models vs full precision | Reduced model size by 70% with minimal accuracy loss (2-3%) allows deployment on edge devices and reduces bandwidth costs |
| Cold start vs performance: Using pre-trained models vs training from scratch | Leveraging pre-trained models reduces training time by 80% and improves initial performance, but requires adaptation to domain-specific data |
| Human annotation vs weak supervision: Quality vs cost trade-off | Human annotation costs $500/user but provides 95% accuracy; weak supervision costs $50/user with ~85% accuracy, suitable for initial model training |
Alternatives considered and rejected
| Alternative | Reason for rejection |
|---|---|
| Transformer-based object detection (DETR) | Higher computational requirements and longer training times; not suitable for real-time edge deployment |
| Single-shot multi-box detector (SSD) | Lower accuracy compared to YOLOv8; insufficient for high-precision applications |
| Fully custom CNN architecture | Requires extensive experimentation and training time; pre-existing architectures like YOLO provide better out-of-the-box performance |
| Cloud-only inference | Increases latency and bandwidth costs; edge deployment provides better user experience for real-time applications |
| No model retraining strategy | Model performance degrades over time due to data drift; requires continuous learning for long-term viability |
Technical debt acknowledged
- Limited support for multi-scale object detection: Current implementation assumes uniform object sizes, which may not generalize well to real-world scenarios with varying scales.
- No built-in model versioning: Manual tracking of model versions increases risk of deploying outdated or incorrect models in production.
- Hardcoded anchor boxes: Using fixed anchor boxes limits flexibility for different object types and image resolutions.
- Inconsistent feature extraction pipeline: Batch vs real-time feature processing uses different pipelines, creating maintenance overhead and potential inconsistency.
- Limited cross-platform compatibility: Model deployment is currently optimized for specific hardware configurations, limiting flexibility in edge device support.
12. Phased Implementation Roadmap
Phase 1: MVP (Weeks 1-6)
Objective: Establish baseline object detection system with rule-based fallback.
Deliverables:
- Rule-based bounding box fallback using OpenCV/Haar cascades
- Basic YOLOv5 model training on 1000 labeled images (COCO subset)
- Simple Flask API for inference serving
- Basic feature extraction pipeline (image preprocessing, normalization)
Dependencies:
- Data labeling pipeline ready
- GPU cluster access (1x V100)
- Basic ML infrastructure (MLflow, Docker)
Critical Path:
- Data labeling → 2. Model training (YOLOv5) → 3. Simple API deployment
Phase 2: Scale & Refine (Weeks 7-12)
Objective: Build scalable feature store, distributed training, and robust A/B testing infrastructure.
Deliverables:
- Feature store (Redis + Postgres) for real-time feature computation
- Distributed training pipeline using Ray or PyTorch Lightning
- A/B testing framework (Flipper-style) for model versioning
- Multi-GPU training support (4x V100 cluster)
- Model version registry with rollback capability
Dependencies:
- Feature store infrastructure
- Distributed training cluster (4x V100)
- A/B testing platform integration
Critical Path:
- Feature store setup → 2. Distributed training pipeline → 3. A/B testing infrastructure
Phase 3: Excellence & Optimization (Weeks 13-18)
Objective: Deploy advanced model architectures, real-time features, and continuous learning capabilities.
Deliverables:
- Multi-task model (detection + classification + segmentation)
- Real-time feature pipeline with Kafka streaming
- Online learning capability using incremental training (Lifelong Learning)
- Production-grade monitoring and alerting system
- Model compression with ONNX/TensorRT optimization
Dependencies:
- Streaming data pipeline (Kafka)
- Real-time feature computation system
- Model compression infrastructure
Critical Path:
- Online learning framework → 2. Real-time features integration → 3. Production monitoring stack
Phase 4: Production Deployment (Weeks 19-20)
Objective: Full production rollout with multi-region support and comprehensive monitoring.
Deliverables:
- Multi-region model serving (AWS/GCP)
- Auto-scaling and load balancing
- Comprehensive alerting and dashboard (Grafana + Prometheus)
- Incident response playbook with rollback procedures
- Model card documentation and compliance audit
Dependencies:
- Multi-region cloud infrastructure
- Production monitoring stack
- Incident response procedures established
Cross-Cutting Dependencies:
- Data labeling pipeline (ongoing)
- Feature store (shared across phases)
- ML platform infrastructure (shared)
- Model registry and versioning (shared)
- A/B testing framework (shared)
Risk Mitigation:
- Model drift: Implement continuous monitoring and retraining triggers
- Latency: Optimize model compression and caching strategies
- Scalability: Design horizontal scaling from day one
- Data quality: Implement data validation and drift detection
- Operational complexity: Maintain clear separation of concerns between phases
Success Metrics:
- Model accuracy (mAP@0.5) > 0.75
- Inference latency < 100ms (p99)
- System availability > 99.9%
- A/B test success rate > 80% for model improvements
- Feature store freshness < 5 minutes