Back to Development Environment

Code Best Practices

Development standards and practices for ML codebases

ML Code Organization
Structuring ML code for maintainability and reproducibility

1. Separate Concerns

Keep data processing, model training, evaluation, and inference in separate modules:

project/
├── data/
│   ├── preprocessing.py
│   ├── feature_engineering.py
│   └── validation.py
├── models/
│   ├── architecture.py
│   ├── training.py
│   └── inference.py
├── evaluation/
│   ├── metrics.py
│   └── validation.py
└── config/
    └── config.yaml

2. Configuration Management

Use configuration files (YAML, JSON) for hyperparameters, paths, and settings:

  • Never hardcode hyperparameters in code
  • Use environment-specific configs (dev, staging, prod)
  • Version control all configuration files
  • Validate configs at startup with schema validation

3. Reproducibility

  • Set Random Seeds: Always set seeds for random number generators (NumPy, PyTorch, TensorFlow)
  • Version Dependencies: Pin exact versions in requirements.txt or poetry.lock
  • Data Versioning: Track which dataset version was used for training
  • Environment Capture: Use tools like Docker or conda to capture exact environments

4. Experiment Tracking

Log all experiments with metadata:

  • Hyperparameters and configuration
  • Model architecture and parameters
  • Training metrics (loss, accuracy, etc.)
  • Data versions and splits
  • Code version (Git commit hash)
  • Environment details (OS, Python version, GPU info)
Data Handling Best Practices

1. Data Validation

  • Validate data schemas before processing
  • Check for missing values, outliers, and data drift
  • Implement data quality checks in pipelines
  • Fail fast on invalid data rather than silently continuing

2. Avoid Data Leakage

  • Split data before any preprocessing
  • Fit scalers/transformers only on training data
  • Never use future information to predict past events
  • Be careful with time-series cross-validation
  • Validate that test set is truly unseen

3. Memory Efficiency

  • Use generators/iterators for large datasets
  • Load data in batches rather than all at once
  • Use appropriate data types (float32 vs float64)
  • Clear intermediate variables when not needed
Model Development Practices

1. Model Architecture

  • Keep models modular and composable
  • Separate model definition from training logic
  • Use factory patterns for model creation
  • Document architectural decisions and trade-offs

2. Training Code

  • Implement checkpointing for long-running training
  • Add early stopping to prevent overfitting
  • Log training progress and metrics regularly
  • Handle GPU/CPU fallback gracefully
  • Make training resumable from checkpoints

3. Inference Code

  • Optimize inference for production (batch processing, quantization)
  • Implement proper error handling and fallbacks
  • Add input validation and sanitization
  • Log predictions for monitoring and debugging
  • Support both batch and single predictions