【问题标题】:Running a Tensorflow model on Android在 Android 上运行 TensorFlow 模型
【发布时间】:2016-01-20 00:46:34
【问题描述】:

我正在尝试找出在 Android 上训练和部署 Tensorflow 模型的工作流程。我知道 StackOverflow 上与此类似的其他问题,但似乎都没有解决我遇到的问题。

在研究了 Tensorflow 存储库中的 Android 示例后,我认为工作流应该是这样的:

  1. 在 Python 中构建和训练 Tensorflow 模型。
  2. 创建一个新图,并将所有相关节点(即不是负责训练的节点)转移到这个新图。经过训练的权重变量作为常量导入,以便 C++ API 可以读取它们。
  3. 用 Java 开发 Android GUI,使用 native 关键字来存根对 Tensorflow 模型的调用。
  4. 运行 javah 为 Tensorflow 本机调用生成 C/C++ 存根代码。
  5. 使用 Tensorflow C++ API 填写存根,以读入和访问经过训练/序列化的模型。
  6. 使用 Bazel 构建 Java 应用、原生 Tensorflow 接口(作为 .so 文件)并生成 APK。
  7. 使用 adb 部署 APK。

    第 6 步是问题所在。 Bazel 将愉快地编译一个本机(针对 OSX).dylib,我可以通过 JNI 从 Java 调用它。同样,Android Studio 会生成一大堆 XML 代码来制作我想要的 GUI。但是,Bazel 希望所有 java 应用程序代码都位于“WORKSPACE”顶级目录中(在 Tensorflow 存储库中),并且 Android Studio 立即从 SDK 链接到各种外部库以制作 GUI(我知道是因为我的Bazel 编译运行在找不到这些资源时失败)。我能找到强制 Bazel 交叉编译 .so 文件的唯一方法是使其成为 Android 规则的依赖规则。直接交叉编译原生库是我更喜欢移植我的 A.S. Bazel 项目的代码。

    我该如何平方? Bazel 应该会编译 Android 代码,但 Android Studio 会生成 Bazel 无法编译的代码。来自 Google 的所有示例都只是为您提供了来自 repo 的代码,而没有任何关于它是如何生成的线索的。据我所知,作为 Android Studio 应用程序一部分的 XML 应该是生成的,而不是手工制作的。如果可以手工制作,我如何避免对所有这些外部库的需要?

    也许我的工作流程有误,或者我不理解 Bazel/Android Studio 的某些方面。任何帮助表示赞赏。

谢谢!

编辑:

我最终做的几件事可能有助于图书馆的成功建设:

  1. 我升级到了最新的 Bazel。
  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 似乎对承认原生库的存在非常挑剔。

【问题讨论】:

  • 制作 .dylib 根本没有帮助,因为 Android 不是 OSX - dylib 是 OSX 唯一的格式。它是 linux,您需要构建一个 .so(这在功能方面几乎相同,但文件格式不同)。此外,Android 中的 XML 都是手工制作的,而不是生成的。几乎没有生成任何 Google 示例中的任何内容。您所期望的事实可能是您的问题的一部分。
  • 另外,除非你的 Tensorflow 软件需要使用 Bazel,否则我从未听说过它被用于 Android 工作。 Gradle 是新标准,Ant 是旧标准。如果您使用的是 Bazel,那么您要么处于领先地位,要么完全在做自己的事情。
  • @amm 你能在 android 上运行它吗?你构建的应用程序的大小是多少?

标签: android tensorflow bazel


【解决方案1】:

在您的 WORKSPACE 文件中设置 Android NDK 后,Bazel 可以为 Android 交叉编译 .so,如下所示:

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 应用程序代码都位于“WORKSPACE”中 顶级目录(在 Tensorflow 仓库中)

当 0.1.4 发布(现在正在推送)并且我们已经向 TensorFlow 和 Protobuf 推送了一些修复时,您可以开始将 TensorFlow 存储库用作远程存储库。在您的 WORKSPACE 文件中进行设置后,您可以使用@tensorflow//foo/bar 标签引用 TensorFlow 规则。

【讨论】:

  • 既然您很可能是Bazel group 的成员,您可以在SO profile 中注明。如果我知道回答的人是开发团队的成员,我更倾向于对答案进行投票。
  • 我的评论是什么意思:我不能将我的应用程序代码保存在与 Tensorflow 根目录分开的目录结构中。
  • 这个解决方案对我不起作用。错误消息:“错误:找不到 cpu 'darwin' 的工具链。”我在我的 WORKSPACE 文件中定义了 android_sdk_repository() 和 android_ndk_repository()。
  • 你是对的,它还没有工作。我应该在发布之前尝试过这些说明,对此感到抱歉。我刚刚更新了说明,它们对我有用。 (我还更新了我的个人资料,表明我在 Bazel 工作。)
  • 我的构建仍然失败并出现同样的问题(没有找到 cpu 'darwin' 的工具链)。这可能与 CROSSTOOL 文件有关。我的安装似乎只有一个在 third_party/gpus/crosstool/ 中。
【解决方案2】:
git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git

注意:--recurse-submodules 对于拉取子模块很重要。

从这里安装 Bazel。 Bazel 是 TensorFlow 的主要构建系统。 现在,编辑WORKSPACE,我们可以在之前克隆的TensorFlow的根目录下找到WORKSPACE文件。

# 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,你可以直接从project使用。

将libandroid_tensorflow_inference_java.jar放入libs文件夹,右键添加为库。

compile files('libs/libandroid_tensorflow_inference_java.jar')

在主目录下创建jniLibs文件夹,将libtensorflow_inference.so放到jniLibs/armeabi-v7a/文件夹中。

现在,我们将能够调用 TensorFlow Java API。

TensorFlow Java API 通过 TensorFlowInferenceInterface 类公开了所有必需的方法。

现在,我们必须使用模型路径调用 TensorFlow Java API 并加载它。

我写了一篇完整的博客here

【讨论】:

  • 当我运行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
猜你喜欢
  • 1970-01-01
  • 2018-04-02
  • 2020-03-19
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
  • 2017-07-20
相关资源
最近更新 更多