2016-01-20 5 views
18

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

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

  1. Создание и обучение Tensorflow модели в Python.
  2. Создайте новый граф и переместите все соответствующие узлы (т. Е. Узлы, ответственные за обучение) на этот новый график. Измененные переменные веса импортируются как константы, так что C++ API может их читать.
  3. Разработка графического интерфейса Android на Java с использованием родного ключевого слова для прерывания вызова модели 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-кода, который сделает 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:

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

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

+0

Создание .dylib вообще не поможет, поскольку Android не является OSX-dylib - это формат только OSX. Это Linux, вам нужно создать .so (что в значительной степени похоже на ту же вещь, но в другом формате). Кроме того, XML в Android все делается вручную НЕ сгенерированным. В значительной степени ничего в любом из примеров Google не генерируется. Тот факт, что вы ожидаете этого, вероятно, является частью вашей проблемы. –

+0

Кроме того, если вашему программному обеспечению Tensorflow не нужно использовать Bazel, я никогда не слышал, чтобы он использовался для работы в Android. Gradle - новый стандарт, а Ant - устаревший стандарт. Если вы используете Bazel, у вас есть либо кровоточащий край, либо полностью твоя собственная вещь. –

+0

@amm Вы могли запустить его на android, какой размер приложения вы создали? – sau

ответ

10

После настройки Android NDK в файле WORKSPACE Базэл могут перекрестно составить .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 wants all of the java app code to be inside the 'WORKSPACE' top-level directory (in the Tensorflow repo)

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

+0

Поскольку вы, скорее всего, являетесь членом группы [Bazel group] (https://github.com/ulfjack/bazel/graphs/contributors), можете отметить это в своем [SO profile] (http://stackoverflow.com/users/4731056/Ulf-Адамс). Я больше склоняюсь к тому, чтобы ответить на вопрос, если я знаю, что человек, отвечающий, является членом команды разработчиков. –

+0

Что я имею ввиду под комментарием: я не могу сохранить код приложения в структуре каталогов отдельно от корня Tensorflow. – amm

+0

Это решение не работает для меня. Сообщение об ошибке: «ОШИБКА: нет инструментальной метки для процессора« darwin ».» У меня есть android_sdk_repository() и android_ndk_repository(), определенные в моем файле WORKSPACE. – amm

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

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

Установите 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 и НДК пути:

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 

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

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

compile files('libs/libandroid_tensorflow_inference_java.jar') 

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

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

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

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

Я написал полный блог here.