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

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

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

  1. построить и обучить модель Tensorflow в Python.
  2. создайте новый график и перенесите все соответствующие узлы (т. е. не узлы, ответственные за обучение) для этого нового графика. Обученные переменные веса импортируются как константы, чтобы API C++ мог их читать.
  3. разработка Android GUI в Java, используя ключевое слово native, чтобы заглушить вызов модели Tensorflow.
  4. запустите javah для генерации кода заглушки C / C++ для собственного вызова Tensorflow.
  5. заполните заглушку с помощью TensorFlow C++ API для чтения и доступа к обученному / сериализованному модель.
  6. используйте Bazel для создания как Java-приложения, так и собственного интерфейса Tensorflow (как a .so file), и генерировать APK.
  7. используйте adb для развертывания APK.

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

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

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

спасибо!

Edit:

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

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

2 ответов


после настройки Android NDK в файле рабочей области Bazel может скомпилировать a .так что для 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

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

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


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

Примечание: -- recurse-submodules важно вытащить подмодули.

установить Bazel отсюда. Bazel является основной системой сборки для TensorFlow. Теперь, отредактировав рабочую область, мы можем найти файл рабочей области в корневом каталоге 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 path:

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)

тогда постройте .Итак, файл.

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 и.Итак, файл. Я уже построили оба .так файл и jar, вы можете напрямую использовать от проект.

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

compile files('libs/libandroid_tensorflow_inference_java.jar')

создать папку jniLibs в main каталог и положите libtensorflow_inference.так в jniLibs/норм-v7a/ папку.

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

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

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

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