Подтвердить что ты не робот

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

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

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

  • Создайте и подготовьте модель Tensorflow в Python.
  • Создайте новый график и переместите все соответствующие узлы (т.е. не узлы, ответственные за обучение) на этот новый график. Измененные переменные весов импортируются как константы, поэтому С++ API может их читать.
  • Разработать графический интерфейс Android на Java, используя ключевое слово native, чтобы отключить вызов модели Tensorflow.
  • Запустите javah, чтобы сгенерировать код заглушки C/С++ для родного вызова Tensorflow.
  • Заполните заглушку, используя API Tensorflow С++ для чтения и доступа к обученной/сериализованной модели.
  • Используйте Bazel для создания BOTH приложения Java, собственного интерфейса Tensorflow (как .so файл) и создания APK.
  • Используйте adb для развертывания APK.

    Этап 6 - проблема. Bazel с радостью скомпилирует родной (OSX).dylib, который я могу вызывать из Java через JNI. Android Studio также будет генерировать целую кучу XML-кода, который сделает GUI, который я хочу. Тем не менее, Bazel хочет, чтобы весь код приложения java находился в директории верхнего уровня WORKSPACE (в репозитории Tensorflow), а Android Studio сразу же ссылается во всех видах внешних библиотек из SDK для создания GUI (я знаю, потому что мой Сбой компиляции Bazel не удается, если он не может найти эти ресурсы). Единственный способ, которым я могу найти, чтобы заставить Bazel перекрестно скомпилировать файл .so, делает его зависимым от правила Android. Непосредственная кросс-компиляция родного lib - это то, что я предпочел бы портировать мой A.S. кода в проект Bazel.

    Как это сделать? Bazel предположительно компилирует код Android, но Android Studio генерирует код, который Bazel не может скомпилировать. Все примеры из Google просто дают вам код из репо без каких-либо подсказок о том, как он был сгенерирован. Насколько я знаю, XML, часть приложения Android Studio должна быть сгенерирована, а не сделана вручную. Если это можно сделать вручную, как мне избежать необходимости во всех этих внешних библиотеках?

    Возможно, я ошибаюсь в работе, или есть какой-то аспект Bazel/Android Studio, который я не понимаю. Любая помощь оценивается.

Спасибо!

Edit:

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

  • Я обновился до последней версии Bazel.
  • Я перестроил 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, по-видимому, очень тонко заявляет о наличии родных libs.

4b9b3361

Ответ 1

После настройки 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 \
    [email protected]_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

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

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

Ответ 2

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

Примечание. - Подмножества -recurse важны для вытягивания подмодулей.

Установите Bazel отсюда. 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 \
   [email protected]_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/.

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

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

Теперь нам нужно вызвать API-интерфейс TensorFlow Java с образцом и загрузить его.

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