web-dev-qa-db-ja.com

Android)でTensorflowモデルを実行する

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は、JavaからJNI経由で呼び出すことができるネイティブ(OSXへの).dylibを喜んでコンパイルします。 Android Studioも同様に、必要なGUIを作成するXMLコードを大量に生成します。ただし、Bazelは、すべてのJavaアプリコードを(Tensorflowリポジトリ内の)「WORKSPACE」トップレベルディレクトリ内に配置することを望んでおり、Android StudioはSDKからのあらゆる種類の外部ライブラリにすぐにリンクしますGUIを作成する(これらのリソースが見つからない場合、Bazelのコンパイル実行が失敗するためです)。 Bazelに.soファイルのクロスコンパイルを強制する唯一の方法は、Androidルールの依存ルールにすることです。ネイティブライブラリを直接クロスコンパイルすることは、A.S。を移植することを好むものです。 Bazelプロジェクトへのコード。

    これを二乗するにはどうすればよいですか? BazelはおそらくAndroidコードをコンパイルしますが、Android StudioはBazelがコンパイルできないコードを生成します。 Googleのすべての例は、リポジトリがどのように生成されたかについての手がかりなしに、リポジトリからコードを提供するだけです。私の知る限り、Android Studioアプリの一部であるXMLは、手動で作成されるのではなく、生成されることになっています。手作業で作成できる場合、これらすべての外部ライブラリの必要性を回避するにはどうすればよいですか?

    ワークフローが間違っているか、Bazel/AndroidStudioの一部の側面が理解できない可能性があります。助けていただければ幸いです。

ありがとう!

編集:

図書館の建設に成功したかもしれない、私がやったことがいくつかありました。

  1. 最新のBazelにアップグレードしました。
  2. ソースからTensorFlowを再構築しました。
  3. 以下に推奨されるBazelBUILDファイルを実装しましたが、いくつか追加しました(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は、ネイティブライブラリの存在を認めるのに非常に気難しいようです。

18
amm

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ルールを参照できます。

10
Ulf Adams
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の両方をビルドしました。 プロジェクト から直接使用できます。

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を呼び出し、ロードする必要があります。

私は完全なブログを書きました ここ

1
Amit Shekhar