Запуск модели Tensorflow на Android

Я пытаюсь понять рабочий процесс для обучения и развертывания модели Tensorflow на Android. Мне известны другие вопросы, похожие на этот, о StackOverflow, но, похоже, ни один из них не решает проблемы, с которыми я столкнулся.

Изучив пример Android из репозитория Tensorflow, я думаю, что рабочий процесс должен быть таким:

  1. Создавайте и обучайте модель Tensorflow на Python.
  2. Создайте новый граф и перенесите все соответствующие узлы (т.е. не узлы, отвечающие за обучение) в этот новый граф. Обученные весовые переменные импортируются как константы, чтобы C ++ API мог их прочитать.
  3. Разработайте графический интерфейс Android на Java, используя ключевое слово native, чтобы заглушить вызов модели Tensorflow.
  4. Запустите javah, чтобы сгенерировать код заглушки C / C ++ для собственного вызова Tensorflow.
  5. Заполните заглушку с помощью API Tensorflow C ++ для чтения и доступа к обученной / сериализованной модели.
  6. Используйте Bazel для создания ОБА приложения Java, собственного интерфейса Tensorflow (в виде файла .so) и создания APK.
  7. Используйте 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, который я не понимаю. Любая помощь приветствуется.

Спасибо!

Изменить:

Я сделал несколько вещей, которые могли успешно способствовать созданию библиотеки:

  1. Перепрошился на последнюю Базель.
  2. Я пересобирал TensorFlow из исходников.
  3. Я реализовал рекомендованный ниже файл 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 кажется очень привередливой к признанию наличия собственных библиотек.


person amm    schedule 20.01.2016    source источник
comment
Создание .dylib совершенно не поможет, поскольку Android - это не OSX-dylib - это формат только для OSX. Это linux, вам нужно создать .so (это почти то же самое, но другой формат файла). Кроме того, XML в Android создается вручную, а НЕ создается. Практически ничего не генерируется ни в одном из примеров Google. Тот факт, что вы этого ожидаете, вероятно, является частью вашей проблемы.   -  person Gabe Sechan    schedule 20.01.2016
comment
Кроме того, если вашему программному обеспечению Tensorflow не требуется использовать Bazel, я никогда не слышал, чтобы он использовался для работы с Android. Gradle - это новый стандарт, а Ant - устаревший стандарт. Если вы используете Bazel, вы либо на переднем крае, либо полностью занимаетесь своим делом.   -  person Gabe Sechan    schedule 20.01.2016
comment
@amm Удалось ли вам запустить его на android, каков размер созданного вами приложения?   -  person sau    schedule 17.03.2016


Ответы (2)


После настройки Android NDK в вашем файле WORKSPACE Bazel может кросс-компилировать .so для Android, например:

cc_binary(
    name = "libfoo.so",
    srcs = ["foo.cc"],
    deps = [":bar"],
    linkstatic = 1,
    linkshared = 1,
)

$ bazel build foo:libfoo.so \
    --crosstool_top=//external:android/crosstool --cpu=armeabi-v7a \
    --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
$ file bazel-bin/foo/libfoo.so
bazel-bin/foo/libfoo.so: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Базель хочет, чтобы весь код Java-приложения находился в каталоге верхнего уровня WORKSPACE (в репозитории Tensorflow)

Когда выйдет 0.1.4 (нажимаем прямо сейчас) и мы внесли некоторые исправления в TensorFlow и Protobuf, вы можете начать использовать репозиторий TensorFlow в качестве удаленного репозитория. После настройки в файле WORKSPACE вы можете ссылаться на правила TensorFlow, используя @tensorflow//foo/bar метки.

person Ulf Adams    schedule 20.01.2016
comment
Поскольку вы, скорее всего, являетесь членом группы Bazel, можете ли вы отметить это в своем Профиль SO. Я более склонен проголосовать за ответ, если знаю, что отвечающий является членом команды разработчиков. - person Guy Coder; 20.01.2016
comment
Что я имею в виду под комментарием: я не могу хранить код моего приложения в структуре каталогов отдельно от корня Tensorflow. - person amm; 21.01.2016
comment
Мне это решение не подходит. Сообщение об ошибке: ОШИБКА: не найдена цепочка инструментов для процессора darwin. У меня есть android_sdk_repository () и android_ndk_repository (), определенные в моем файле WORKSPACE. - person amm; 21.01.2016
comment
Вы правы, пока не работает. Я должен был попробовать инструкции перед публикацией, извините за это. Я обновил инструкцию только сейчас, и они у меня работают. (Я также обновил свой профиль, чтобы указать, что я работаю над Bazel.) - person Ulf Adams; 21.01.2016
comment
Моя сборка по-прежнему не работает с той же проблемой (для процессора darwin не найдена цепочка инструментов). Это может иметь какое-то отношение к файлу CROSSTOOL. Похоже, что в моей установке только один из них находится в третьем_партийном / gpus / crossstool /. - person amm; 21.01.2016
comment
@UlfAdams Спасибо за обновление профиля SO. Приятно знать. - person Guy Coder; 21.01.2016
comment
Не знаю, как мне удалось снова испортить инструкции. Я думал, что скопировал их. Теперь они должны работать - обратите внимание на дополнительный флаг --host_crosstool_top. Это глупо, но на данный момент это необходимо. : - / - person Ulf Adams; 21.01.2016

git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git

Примечание: --recurse-submodules важен для извлечения подмодулей.

Установите Базель отсюда. Bazel - это основная система сборки для TensorFlow. Теперь отредактируйте WORKSPACE, мы можем найти файл WORKSPACE в корневом каталоге TensorFlow, который мы клонировали ранее.

# Uncomment and update the paths in these entries to build the Android demo.
#android_sdk_repository(
#    name = "androidsdk",
#    api_level = 23,
#    build_tools_version = "25.0.1",
#    # Replace with path to Android SDK on your system
#    path = "<PATH_TO_SDK>",
#)
#
#android_ndk_repository(
#    name="androidndk",
#    path="<PATH_TO_NDK>",
#    api_level=14)

Как показано ниже с нашими путями sdk и ndk:

android_sdk_repository(
    name = "androidsdk",
    api_level = 23,
    build_tools_version = "25.0.1",
    # Replace with path to Android SDK on your system
    path = "/Users/amitshekhar/Library/Android/sdk/",
)
android_ndk_repository(
    name="androidndk",
    path="/Users/amitshekhar/Downloads/android-ndk-r13/",
    api_level=14)

Затем создайте файл .so.

bazel build -c opt //tensorflow/contrib/android:libtensorflow_inference.so \
   --crosstool_top=//external:android/crosstool \
   --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
   --cpu=armeabi-v7a

Замена armeabi-v7a на нашу желаемую целевую архитектуру. Библиотека будет располагаться по адресу:

bazel-bin/tensorflow/contrib/android/libtensorflow_inference.so

Чтобы создать аналог Java:

bazel build //tensorflow/contrib/android:android_tensorflow_inference_java

Мы можем найти файл JAR по адресу:

bazel-bin/tensorflow/contrib/android/libandroid_tensorflow_inference_java.jar

Теперь у нас есть файлы jar и .so. Я уже создал и файл .so, и jar, которые вы можете использовать напрямую из проекта .

Поместите libandroid_tensorflow_inference_java.jar в папку libs, щелкните правой кнопкой мыши и добавьте в качестве библиотеки.

compile files('libs/libandroid_tensorflow_inference_java.jar')

Создайте папку jniLibs в основном каталоге и поместите libtensorflow_inference.so в папку jniLibs / armeabi-v7a /.

Теперь мы сможем вызвать TensorFlow Java API.

API-интерфейс TensorFlow Java предоставляет все необходимые методы через класс TensorFlowInferenceInterface.

Теперь нам нужно вызвать TensorFlow Java API с путем к модели и загрузить его.

Я написал полный блог здесь.

person Amit Shekhar    schedule 11.03.2017
comment
При запускеbazel build //tensorflow/contrib/android:android_tensorflow_inference_java выдает эту ошибку ERROR: /tensorflow-1.5.0/WORKSPACE:20:1: no such package '@androidsdk//': android_sdk_repository requires that at least one Android SDK Platform is installed in the Android SDK. Please install an Android SDK Platform through the Android SDK manager. and referenced by '//external:android/sdk' ERROR: Analysis of target '//tensorflow/contrib/android:android_tensorflow_inference_java' failed; build aborted: Loading failed - person Effective_cellist; 26.03.2018