LoginSignup
4
3

More than 5 years have passed since last update.

Androidでtensorflowを使う時に、はまった話

Last updated at Posted at 2017-10-25

概要

Pythonで作ったtensorflowのモデルをAndroidでも使いたいと思って、色々試したが結構躓いたので、経緯を記録しておく。最終的に無事にAndroid上でtensorflowを動作させることができたが、原因はまとまってない。

<環境>
PC:mac
開発環境:AndroidStudio
tensorflowのプログラム:パラメータが格納されたmodel.pbと、Tensor.create( )、session.runner( )などが書かれたLSTM.javaがあるのみ

初動

Bazelとか使いたくなかったので、以下を参考に進めた。その上で、問題が発生してつまづいた部分を以下に記録する。
https://qiita.com/icchi_h/items/a1df9f27569714edfc5e

問題

いくつか問題が出てきたので、個別に対処していった。
問題1:model.pbが読めない
問題2:tensorflowがimportできない
問題3:アプリが以下のエラー吐いて強制終了する
No implementation found for native Lorg/tensorflow/TensorFlow;.version:()Ljava/lang/String;
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lorg/tensorflow/TensorFlow;
FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: Cannot find TensorFlow native library for OS: linux, architecture: i686.

問題1:model.pbが読み込めない

普段iOSのアプリを開発しているとこういうのは結構不便なのだが、AndroidStudioではassetsフォルダから、ローカルファイルを読み込むようになっている。

1:app/src/mainにassetsフォルダを追加(追加の仕方に注意)
  追加の仕方:mainを右クリック→「New」→「Folder」→「Assets Folder」

2:作ったassetsフォルダにmodel.pbファイルを配置

3:MainActivity.javaのonCreate内で以下のコードを呼ぶ
  byte[] graphDef = readByteFile(String.valueOf("model.pb"))

  readFileToByteは自作関数で以下のように記述した。

   byte[] readByteFile(String filePath) {
        try {
            byte[] b = new byte[1];
            InputStream fis = this.getAssets().open(filePath);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while (fis.read(b) > 0) {
                baos.write(b);
            }
            baos.close();
            fis.close();
            b = baos.toByteArray();

            return b;
        }catch(Exception ex){
            System.out.println(ex.toString());
            return null;
        }
    }

問題2:tensorflowがimportできない

今回使用したLSTM.javaには以下のimportが記述してあった。

import org.tensorflow.Graph;
import org.tensorflow.Session;
import org.tensorflow.Tensor;

これを読むためにapp内の「build.gradle」に以下の記述を追加した。
ちなみに、「1.2.0」と「1.2.0-preview」があるらしく、「copyTo」がpreviewしか対応していなかったため、previewを記述。その後、AndroidStudioのSyncボタンを押下。

dependencies {

    ...

    compile 'org.tensorflow:tensorflow-android:1.2.0-preview'
    //compile 'org.tensorflow:tensorflow:1.2.0'

   ...

}

問題3:エラーを吐いて強制終了する

No implementation found for native Lorg/tensorflow/TensorFlow;.version:()Ljava/lang/String;
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lorg/tensorflow/TensorFlow;
FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: Cannot find TensorFlow native library for OS: linux, architecture: i686.

というエラーだが、これに関する解決策が驚くほど出てこなくて困った。(私の勉強不足でもあるが)

いくつかやった事があるので以下に記すが、いらない操作もあるかもしれない。

1. soファイルを追加する

以下のリンクから、「最新成功ビルドの成果物 → out → native → (すべてのファイルをzipで)」という操作で、ファイルをダウンロードする。
http://ci.tensorflow.org/view/Nightly/job/nightly-android/

AndroidStudioでappの直下にlibsフォルダを追加する。
libsフォルダ内に先ほどダウンロードしたnativeフォルダ内の「libtensorflow_inference.so」内の全てのフォルダをlibsフォルダに追加する。ディレクトリ構成は以下のようになるはず。
-app
--libs
---arm64-v8a
----libtensorflow_inference.so
---armeabi-v7a
----libtensorflow_inference.so
---x86
----libtensorflow_inference.so
---x86_64
----libtensorflow_inference.so

2. MainAcitivityにloadLibraryの追記をする

public class MainActivity extends AppCompatActivity {

    ....

    static {
        System.loadLibrary("tensorflow_inference");
    }

    ....

}

3. app内のbuild.gradleのsourceSetsを変更する

android {

    ...

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    ...

}

とりあえず、これでなんとか動いた。
結局何が正解なのかは分からないが、備忘録として残しておく。

4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3