在Android上运行Tensorflow模型 [英] Running a Tensorflow model on Android

查看:567
本文介绍了在Android上运行Tensorflow模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to figure out the workflow for training and deploying a Tensorflow model on Android. I'm aware of the other questions similar to this one on StackOverflow, but none of them seem to address the problems I've run into.

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

After studying the Android example from the Tensorflow repository, this is what I think the workflow should be:

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

  1. Build and train Tensorflow model in Python.
  2. Create a new graph, and transfer all relevant nodes (i.e. not the nodes responsible for training) to this new graph. Trained weight variables are imported as constants so that the C++ API can read them.
  3. Develop Android GUI in Java, using the native keyword to stub out a call to the Tensorflow model.
  4. Run javah to generate the C/C++ stub code for the Tensorflow native call.
  5. Fill in the stub by using the Tensorflow C++ API to read in and access the trained/serialized model.
  6. Use Bazel to build BOTH the Java app, the native Tensorflow interface (as a .so file), and generate the APK.
  7. Use adb to deploy the APK.

第6步是问题所在. Bazel将愉快地编译本机(至OSX).dylib,我可以通过JNI从Java调用它.同样,Android Studio将生成一堆XML代码,这些代码构成了我想要的GUI.但是,Bazel希望所有Java应用程序代码都在"WORKSPACE"顶级目录(在Tensorflow存储库中)内,Android Studio立即从SDK链接各种外部库以制作GUI(我知道这是因为无法找到这些资源时,Bazel编译运行将失败.我发现强迫Bazel交叉编译.so文件的唯一方法是使它成为Android规则的从属规则.我宁愿直接交叉编译本机lib,也不愿移植我的A.S.代码到Bazel项目.

Step 6 is the problem. Bazel will happily compile a native (to OSX) .dylib that I can call from Java via the JNI. Android Studio, likewise, will generate a whole bunch of XML code that makes the GUI I want. However, Bazel wants all of the java app code to be inside the 'WORKSPACE' top-level directory (in the Tensorflow repo), and Android Studio immediately links in all sorts of external libraries from the SDK to make GUIs (I know because my Bazel compile run fails when it can't find these resources). The only way I can find to force Bazel to cross-compile a .so file is by making it a dependent rule of an Android rule. Directly cross-compiling a native lib is what I'd prefer to porting my A.S. code to a Bazel project.

我该如何平方? Bazel应该会编译Android代码,但是Android Studio会生成Bazel无法编译的代码. Google提供的所有示例都只是为您提供了一个仓库中的代码,而没有任何有关其生成方式的线索.据我所知,Android Studio应用程序中的XML应该是生成的,而不是手工生成的.如果可以手工制作,如何避免使用所有这些外部库?

How do I square this? Bazel will supposedly compile Android code, but Android Studio generates code that Bazel can't compile. All the examples from Google simply give you code from a repo without any clue as to how it was generated. As far as I know, the XML that's part of an Android Studio app is supposed to be generated, not made by hand. If it can be made by hand, how do I avoid the need for all those external libraries?

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

Maybe I'm getting the workflow wrong, or there's some aspect of Bazel/Android Studio that I'm not understanding. Any help appreciated.

谢谢!

我最终要做的几件事可能成功地帮助了图书馆建设:

There were several things that I ended up doing that might have contributed to the library building successfully:

  1. 我升级到了最新的Bazel.
  2. 我从源头重建了TensorFlow.
  3. 我实现了下面推荐的Bazel BUILD文件,并做了一些补充(摘自Android示例):

  1. I upgraded to the latest Bazel.
  2. I rebuilt TensorFlow from source.
  3. I implemented the recommended Bazel BUILD file below, with a few additions (taken from the Android example):

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在承认本地库的存在方面似乎非常挑剔.

I haven't verified that this library can be loaded and used in Android yet; Android Studio 1.5 seems to be very finicky about acknowledging the presence of native libs.

推荐答案

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

After setting up an Android NDK in your WORKSPACE file, Bazel can cross-compile a .so for Android, like this:

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仓库中)

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//foo/bar标签引用TensorFlow规则.

When 0.1.4 is released (pushing it right now) and we have pushed some fixes to TensorFlow and Protobuf, you can start using the TensorFlow repo as a remote repository. After setting it up in your WORKSPACE file, you can then refer to TensorFlow rules using @tensorflow//foo/bar labels.

这篇关于在Android上运行Tensorflow模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆