Я пытаюсь понять рабочий процесс для обучения и развертывания модели Tensorflow на Android. Мне известны другие вопросы, похожие на этот, о StackOverflow, но, похоже, ни один из них не решает проблемы, с которыми я столкнулся.
Изучив пример Android из репозитория Tensorflow, я думаю, что рабочий процесс должен быть таким:
- Создавайте и обучайте модель Tensorflow на Python.
- Создайте новый граф и перенесите все соответствующие узлы (т.е. не узлы, отвечающие за обучение) в этот новый граф. Обученные весовые переменные импортируются как константы, чтобы C ++ API мог их прочитать.
- Разработайте графический интерфейс Android на Java, используя ключевое слово native, чтобы заглушить вызов модели Tensorflow.
- Запустите javah, чтобы сгенерировать код заглушки C / C ++ для собственного вызова Tensorflow.
- Заполните заглушку с помощью API Tensorflow C ++ для чтения и доступа к обученной / сериализованной модели.
- Используйте Bazel для создания ОБА приложения Java, собственного интерфейса Tensorflow (в виде файла .so) и создания APK.
Используйте adb для развертывания APK.
Шаг 6 - проблема. Bazel с радостью скомпилирует собственный (для OSX) .dylib, который я могу вызывать из Java через JNI. Android Studio также сгенерирует целый набор XML-кода, который сделает нужный мне графический интерфейс. Однако Bazel хочет, чтобы весь код Java-приложения находился в каталоге верхнего уровня WORKSPACE (в репозитории Tensorflow), а Android Studio немедленно подключает все виды внешних библиотек из SDK для создания графических интерфейсов (я знаю, потому что мои Запуск компиляции Bazel завершается ошибкой, если он не может найти эти ресурсы). Единственный способ заставить Bazel выполнять кросс-компиляцию файла .so - это сделать его зависимым правилом правила Android. Прямая кросс-компиляция нативной библиотеки - это то, что я предпочел бы перенести на свой A.S. код для проекта Bazel.
Как мне это исправить? Предполагается, что Bazel будет компилировать код Android, но Android Studio генерирует код, который Bazel не может скомпилировать. Все примеры от Google просто дают вам код из репозитория, не имея ни малейшего представления о том, как он был сгенерирован. Насколько мне известно, XML, который является частью приложения Android Studio, должен быть сгенерирован, а не создан вручную. Если это можно сделать вручную, как мне избежать необходимости во всех этих внешних библиотеках?
Возможно, я неправильно понимаю рабочий процесс, или есть какой-то аспект Bazel / Android Studio, который я не понимаю. Любая помощь приветствуется.
Спасибо!
Изменить:
Я сделал несколько вещей, которые могли успешно способствовать созданию библиотеки:
- Перепрошился на последнюю Базель.
- Я пересобирал TensorFlow из исходников.
Я реализовал рекомендованный ниже файл Bazel BUILD с некоторыми дополнениями (взятыми из примера Android):
cc_binary( name = "libName.so", srcs = ["org_tensorflowtest_MyActivity.cc", "org_tensorflowtest_MyActivity.h", "jni.h", "jni_md.h", ":libpthread.so"], deps = ["//tensorflow/core:android_tensorflow_lib", ], copts = [ "-std=c++11", "-mfpu=neon", "-O2", ], linkopts = ["-llog -landroid -lm"], linkstatic = 1, linkshared = 1, ) cc_binary( name = "libpthread.so", srcs = [], linkopts = ["-shared"], tags = [ "manual", "notap", ], )
Я еще не проверял, можно ли эту библиотеку загружать и использовать в Android; Android Studio 1.5 кажется очень привередливой к признанию наличия собственных библиотек.