I Swapped the ML Model in My Android App. The App Had No Idea.
Summary
An Android application, FinRisk, demonstrated how an interface-driven design enables seamless on-device ML model upgrades without modifying the Android codebase. The author replaced a logistic regression model with a neural network to resolve a critical failure where the original model incorrectly approved a high-income, high-debt loan applicant (input [1.0, 0.8, 1.0] yielded 0.677 confidence for APPROVE). The new neural network, with 41 parameters compared to the logistic regression's 4, correctly produced 0.080 for DENY. This upgrade necessitated seven changes in the Python training script, including adjusting model definition, strengthening training data labels, extending training duration from 30 to 200 epochs, refining validation strategy, and ensuring reproducibility with TensorFlow seeding. Despite these significant backend changes and a model size increase from 1.8 KB to 2.6 KB, the Android app's Kotlin code remained untouched, leveraging a "RiskClassifier" interface and Hilt for dependency injection to abstract model implementation details.
Key takeaway
For Android engineers integrating ML features, designing with a "RiskClassifier" interface and dependency injection from the outset is crucial. This approach insulates your app's codebase from model implementation details, transforming future model upgrades from complex Kotlin changes into simple file replacements. You avoid costly refactoring and ensure your application remains agile as ML models evolve.
Key insights
Interface-driven design with dependency injection enables seamless ML model upgrades in Android apps.
Principles
- Decouple model contract from implementation.
- Training data must contain the learnable signal.
- Verify model behavior, not internal state.
Method
Implement a "RiskClassifier" interface for model inference, using a dependency injection framework like Hilt to bind specific ".tflite" implementations at runtime, allowing file-based model swaps.
In practice
- Strengthen training data labels for critical edge cases.
- Employ explicit 70/15/15 train/val/test data splits.
- Seed `tf.random.set_seed()` for neural network reproducibility.
Topics
- On-device ML
- TFLite
- Dependency Injection
- Interface Design
- Neural Networks
- Model Training
Code references
Best for: AI Engineer, Machine Learning Engineer, Software Engineer
Related on AIssential
Editorial summary, takeaway, and curation by AIssential. Original article published by Towards AI - Medium.