Разработка машинного обучения (TensorFlow Lite) в мобильном приложении
TensorFlow Lite — один из двух стандартов на рынке мобильного on-device ML (рядом с Core ML и ONNX Runtime). Его сила — в контроле: вы сами выбираете делегат, уровень квантизации и способ загрузки модели. Его слабость — в той же гибкости: неправильный делегат или неоптимизированная модель дают производительность хуже, чем облачный API.
Делегаты: где большинство ошибается
TfLiteGpuDelegateV2 на Android даёт реальный прирост только при батч-инференсе или на моделях с тяжёлыми свёртками (EfficientDet, MobileNet SSD). На лёгких моделях (MobileNetV2 с 224×224 входом) GPU-делегат работает медленнее CPU из-за overhead на передачу данных между памятью и GPU. Мы профилировали это на Xiaomi Redmi Note 11: CPU 78 ms, GPU 112 ms. Вывод: всегда измеряйте на целевых устройствах, не на флагманах.
NNAPI-делегат (NnApiDelegate) теоретически использует аппаратный акселератор (DSP, NPU), но на практике поддержка операций очень неровная. Если модель содержит нестандартные op (например, кастомный squeeze-excitation блок), NNAPI молча падает на CPU. Обязательно логируйте InterpreterApi.Options.setNumThreads и проверяйте через Interpreter.getSignatureInputs(), какие операции реально выполняются на акселераторе.
На iOS TFLite использует CoreMLDelegate — это обёртка над Core ML. Если таргет >= iOS 12, CoreMLDelegate автоматически задействует Neural Engine для поддерживаемых слоёв. Слои без поддержки CPU Core ML падают на CPU-интерпретатор TFLite. Смешанное выполнение работает, но латентность непредсказуемая без профилирования.
Оптимизация модели перед деплоем
Квантизация — обязательный шаг для мобиля. Три варианта:
- Post-training dynamic range quantization — самый простой, веса сжимаются в INT8, активации остаются float. Размер модели уменьшается в ~4 раза, скорость растёт на 20–40% на CPU.
- Post-training integer quantization — веса и активации в INT8, требует калибровочный датасет. Нужен для NNAPI и Edge TPU.
- Quantization-aware training (QAT) — лучшая точность при INT8, но требует дообучения модели.
Использование tf.lite.TFLiteConverter с optimizations = [tf.lite.Optimize.DEFAULT] покрывает первые два случая. QAT настраиваем через tfmot.quantization.keras.quantize_model.
Пример из практики: приложение для распознавания растений (классификатор EfficientNetB0, 29 MB float32). После full integer quantization — 7.4 MB, инференс с NNAPI на Pixel 7 — 18 ms против 95 ms на float32 CPU. На Snapdragon 778G с NNAPI пришлось откатиться на CPU из-за неподдерживаемой LEAKY_RELU операции — добавили fallback через NnApiDelegate.Options.setAllowFp16PrecisionForFp32.
Интеграция в приложение
На Android используем org.tensorflow:tensorflow-lite + org.tensorflow:tensorflow-lite-gpu через Gradle. Для поддержки Task Library (ImageClassifier, ObjectDetector) — org.tensorflow:tensorflow-lite-task-vision. Task Library берёт на себя предобработку изображения (ресайз, нормализация), что убирает значительный пласт boilerplate.
На iOS — CocoaPods pod 'TensorFlowLiteSwift' или Swift Package Manager (начиная с TFLite 2.13). Инференс оборачиваем в actor для thread-safety:
actor TFLiteInferenceService {
private let interpreter: Interpreter
func classify(pixelBuffer: CVPixelBuffer) throws -> [Float] { ... }
}
Загрузка модели из бандла или по URL с верификацией через SHA-256. Для OTA-обновлений — Firebase Remote Config с URL модели, download через URLSession.downloadTask в фоне.
Сроки
Интеграция готовой TFLite-модели с выбором делегата и базовой оптимизацией — 1 неделя. Полный цикл с конвертацией, квантизацией, тестированием на таргетных устройствах и OTA-обновлением — 2–3 недели. Стоимость рассчитывается индивидуально после анализа модели и требований.







