Termux превращает обычный Android-смартфон или планшет в рабочую среду командной строки. Для задач машинного обучения это особенно полезно: можно быстро поставить зависимости, запускать Python-скрипты, прогонять TensorFlow Lite модели, собирать логи и воспроизводить эксперименты прямо «в полевых условиях».
В этой статье разберём, как организовать рабочий стенд Termux + Python + TensorFlow Lite, как запускать inference и как проводить отладку типичных ошибок: версии библиотек, проблемы с загрузкой модели, несовместимость форматов и производительность на устройстве.
Требования и подготовка среды
Подготовьте Android-устройство с установленным Termux. Для установки пакетов понадобятся:
- Интернет (для скачивания пакетов и зависимостей);
- Достаточно места во внутренней памяти или на карте microSD;
- Умение запускать команды в Termux.
Проверим базовые параметры и обновим индексы пакетов.
pkg update && pkg upgrade -yУстановка Python в Termux
Установка Python в Termux обычно выполняется стандартным способом через пакетный менеджер. Далее понадобятся виртуальная среда и базовые инструменты.
pkg install -y python python-dev clangСоздадим рабочую директорию и виртуальную среду (рекомендуется для чистоты зависимостей проекта).
mkdir -p ~/ml_tflite_project
cd ~/ml_tflite_project
python -m venv .venv
source .venv/bin/activateОбновим pip.
python -m pip install --upgrade pip setuptools wheelУстановка TensorFlow Lite runtime
Для запуска TFLite на мобильном Python-коде удобно использовать пакет, предоставляющий интерпретатор (interpreter). В зависимости от архитектуры и доступности пакетов в репозитории Python для Android могут отличаться варианты установки. Начнём с попытки установить tflite_runtime.
pip install tflite-runtimeЕсли установка tflite_runtime недоступна, иногда помогает установка варианта «от разработчиков» или сборка через дополнительные шаги. Практически это зависит от конкретной версии Termux/ABI и доступности wheel для вашего окружения. На практике мы обычно идём так:
- Проверяем, где есть подходящий wheel;
- Фиксируем версии Python и пакетов;
- Если нужно — используем минимальный runtime, который реально ставится в вашей конфигурации.
Проверим, что интерпретатор импортируется.
python -c "import tflite_runtime; print('tflite_runtime OK')"Подготовка модели и структуры проекта
TensorFlow Lite модели — это файлы .tflite. Положите модель в проект, например:
mkdir -p ~/ml_tflite_project/model
# скопируйте your_model.tflite в этот каталогДополнительно могут понадобиться:
- файл меток классов (labels);
- скрипт предобработки входных данных;
- конфиг нормализации (mean/std) и размер входного тензора.
Ниже пример универсальной структуры.
~/ml_tflite_project/
model/
your_model.tflite
app/
run_infer.pyЗапуск inference: минимальный пример на Python
Создадим скрипт run_infer.py. Он загрузит модель, подготовит input и выполнит inference.
mkdir -p app
nano app/run_infer.pyПример кода (адаптируйте под вашу модель: форма входа, тип данных, способ предобработки):
import numpy as np
from tflite_runtime.interpreter import Interpreter
MODEL_PATH = "model/your_model.tflite"
def main():
interpreter = Interpreter(model_path=MODEL_PATH)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
print("Input details:", input_details)
print("Output details:", output_details)
# Предполагаем модель вида: input_shape = (1, H, W, C) или (1, N)
input_shape = input_details[0]["shape"]
input_dtype = input_details[0]["dtype"]
# Здесь пример: заглушка входа.
# В реальном проекте замените на предобработанные данные (из изображения/текста/табличных признаков).
x = np.zeros(input_shape, dtype=input_dtype)
interpreter.set_tensor(input_details[0]["index"], x)
interpreter.invoke()
y = interpreter.get_tensor(output_details[0]["index"])
print("Raw output:", y)
if name == "main":
main()Запустим скрипт.
python app/run_infer.pyТиповой workflow: предобработка и приведение типов
Большинство проблем на этапе запуска inference связаны не с самим интерпретатором, а с несовпадением ожиданий модели:
- Форма входа (shape). Например, модель ожидает
[1, 224, 224, 3], а вы передаёте[224, 224, 3]или[1, 3, 224, 224]. - Тип данных (dtype). Часто требуется
float32илиuint8(квантованные модели). - Масштабирование. Для float моделей используются нормализация и средние значения, а для quantized — квантование с коэффициентами
scaleиzero_point.
Чтобы увидеть параметры квантования, загляните в details входа. Часто полезны поля вроде quantization и index.
python -c "from tflite_runtime.interpreter import Interpreter; i=Interpreter(model_path='model/your_model.tflite'); i.allocate_tensors(); print(i.get_input_details())"Если модель квантованная, корректная логика выглядит так:
- Берём «сырые» значения признаков;
- Приводим к диапазону/формату, ожидаемому моделью;
- Применяем квантование (если вы делаете это вручную), используя scale/zero_point из input_details;
Если вы хотите, пришлите (или опишите) параметры входа из get_input_details() — подстроим пример под вашу модель.
Отладка: как быстро понять, где ошибка
Далее — практический чек-лист. Он экономит время, когда модель не запускается или вывод «странный».
1) Ошибки загрузки модели
Если вы видите сообщения вида «Model not found» или «Error reading model», проверьте:
- Путь к
.tfliteотносительно текущей директории; - Права на чтение файла;
- Целостность файла (не скопировался ли он битым).
ls -l model
# и проверьте, что файл действительно там и читается2) Несовпадение shape
Типичная ошибка: интерпретатор ругается при set_tensor или при вызове invoke. Решение: сравнить форму входа в вашем скрипте с тем, что возвращает get_input_details()[0]["shape"].
python -c "from tflite_runtime.interpreter import Interpreter; i=Interpreter(model_path='model/your_model.tflite'); i.allocate_tensors(); print(i.get_input_details()[0]['shape'])"3) Несовпадение dtype
Если модель ожидает float32, а вы подали float64 или наоборот, получите исключения или некорректные результаты. Решение: приводить входной тензор к input_dtype.
# пример приведения
x = x.astype(input_dtype)4) Проблемы с предобработкой и нормализацией
Если скрипт «успешно запускается», но модель выдает заведомо неверные ответы, часто причина в несоответствии предобработки тренировки. Проверьте:
- Нормализацию (mean/std или диапазон);
- Порядок каналов (RGB vs BGR);
- Масштабирование (например,
0..255vs0..1); - Обрезку/resize с теми же параметрами.
5) Производительность и стабильность
На мобильном устройстве скорость inference зависит от модели, наличия делегатов и архитектуры. Даже без сложной оптимизации вы можете:
- Ограничить логирование в циклах;
- Держать интерпретатор переиспользуемым (создавать один раз);
- Использовать подходящую версию runtime;
- Проверять размер и тип модели (квантованные модели обычно быстрее).
Пример переиспользования интерпретатора:
from tflite_runtime.interpreter import Interpreter
import numpy as np
class TFLiteRunner:
def init(self, model_path):
self.interpreter = Interpreter(model_path=model_path)
self.interpreter.allocate_tensors()
self.input_details = self.interpreter.get_input_details()
self.output_details = self.interpreter.get_output_details()
def predict(self, x):
x = x.astype(self.input_details[0]["dtype"])
self.interpreter.set_tensor(self.input_details[0]["index"], x)
self.interpreter.invoke()
return self.interpreter.get_tensor(self.output_details[0]["index"])Загрузка данных: файлы, картинки и распаковка входа
Если вы работаете с изображениями, вам обычно понадобится распаковка входа в тензор и приведение к ожидаемой форме. В рамках Termux чаще всего используют NumPy и библиотеку для чтения изображений (например, через Pillow, если она доступна в вашей среде).
Базовый подход:
pip install pillow numpyСхема предобработки зависит от модели. Общая идея:
- Открыть изображение;
- Сделать resize до требуемого размера;
- Преобразовать в массив;
- Сделать нормализацию/квантацию;
- Собрать batch-мерность (часто добавляют размерность 1).
Если ваша модель под компьютерное зрение — опишите входные параметры из get_input_details(), и мы адаптируем пример точнее.
Сценарий: классификация с labels и форматированным выводом
Для удобства можно добавить чтение файла меток и вывод вероятностей/класса. Пример (универсальный, требует адаптации под вашу модель):
import numpy as np
from tflite_runtime.interpreter import Interpreter
MODEL_PATH = "model/your_model.tflite"
LABELS_PATH = "model/labels.txt"
def load_labels(path):
with open(path, "r", encoding="utf-8") as f:
return [line.strip() for line in f if line.strip()]
def main():
labels = load_labels(LABELS_PATH)
interpreter = Interpreter(model_path=MODEL_PATH)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
input_shape = input_details[0]["shape"]
input_dtype = input_details[0]["dtype"]
# TODO: заменить на реальные входные данные
x = np.zeros(input_shape, dtype=input_dtype)
interpreter.set_tensor(input_details[0]["index"], x)
interpreter.invoke()
logits = interpreter.get_tensor(output_details[0]["index"])
logits = np.squeeze(logits)
pred = int(np.argmax(logits))
score = float(np.max(logits))
print("Prediction:", labels[pred] if pred < len(labels) else pred)
print("Score:", score)
if name == "main":
main()Запуск:
python app/run_infer.pyОтладка в реальном времени: логи и контроль окружения
Для диагностики удобно сохранять версии и печатать детали интерпретатора. Это помогает понять, что именно выполняется на устройстве.
python -c "import sys, platform; print(sys.version); print(platform.platform())"python -c "import tflite_runtime; print('tflite_runtime version:', getattr(tflite_runtime,'version','unknown'))"Добавляйте в скрипт вывод:
- shape/dtype входа;
- shape/dtype выхода;
- квантационные параметры (если есть);
- и, при необходимости, промежуточные статистики входных данных (min/max).
Частые проблемы и практические решения (коротко)
- «Пакет не ставится»: фиксируйте версию Python и используйте виртуальную среду; проверяйте, подходит ли пакет для вашего ABI.
- «Ошибка set_tensor»: проверьте shape и dtype.
- «Вывод не похож на ожидаемый»: проверьте предобработку и нормализацию; для quantized моделей — проверьте корректность квантования.
- «Медленно»: попробуйте квантованную модель и переиспользование интерпретатора; минимизируйте копирование массивов.
Вариант для разработки: перенос экспериментов между устройством и ПК
Практика такая: вы тренируете/экспортируете модель на ПК, а на Android делаете inference и отладку предобработки. Для быстрого обмена файлами удобно:
- копировать
.tfliteи labels в Termux-папку; - при необходимости использовать локальную сеть для передачи файлов (без задач обхода блокировок).
Если вы используете локальную сеть для разработки (например, чтобы быстро подгружать файлы в Termux), опишите ваш сценарий — подскажу безопасный и простой способ обмена.
Заключение
Termux в связке с Python и TensorFlow Lite позволяет запускать модели машинного обучения прямо на Android и удобно отлаживать pipeline: от загрузки .tflite до проверки shape/dtype, предобработки и качества inference. Самые частые причины ошибок — несовпадение формы/типа входных данных и несоответствие нормализации, поэтому начните с вывода get_input_details() и сверки ожиданий модели.
Если хотите, мы в РыбинскЛАБ поможем адаптировать пример под вашу конкретную модель (квантованную/неквантованную), настроить окружение Termux и выстроить стабильный процесс запуска и отладки inference на мобильном устройстве.