ML Kit を使用して推論に TensorFlow Lite モデルを使用する(Android)

ML Kit を使用すると、TensorFlow Lite モデルを使用して端末上で推論を実行できます。

この API を使用するには、Android SDK レベル 16(Jelly Bean)以上が必要です。

この API の使用例については、GitHub の ML Kit クイックスタート サンプルを参照するか、Codelab を試してみてください。

準備

  1. まだアプリに Firebase を追加していない場合は、スタートガイドの手順に沿って追加してください。
  2. アプリレベルの build.gradle ファイルに ML Kit の依存関係を含めます。
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-model-interpreter:16.2.0'
    }
    
  3. 使用する TensorFlow モデルを TensorFlow Lite(tflite)形式に変換します。TOCO: TensorFlow Lite 最適化コンバーターをご覧ください。

モデルをホストまたはバンドルする

アプリの推論に TensorFlow Lite モデルを使用するには、事前に ML Kit でモデルを利用可能にしておく必要があります。ML Kit は、Firebase を使用してリモートにホストされている TensorFlow Lite モデル、端末にローカルに保存されている TensorFlow Lite モデルのいずれか、またはその両方を使用できます。

モデルを Firebase にホストし、ローカルにも保存すると、モデルの最新バージョンが利用可能な場合にそのバージョンを常に利用できます。Firebase にホストされたモデルが利用できない場合でも、アプリの ML 機能は引き続き動作します。

モデルのセキュリティ

TensorFlow Lite モデルを ML Kit で利用可能にする方法を問わず、ML Kit はそれらのモデルを標準のシリアル化された protobuf 形式でローカル ストレージに格納します。

理論上、これは誰でもモデルをコピーできることを意味します。ただし、実際には、ほとんどのモデルはアプリケーションに固有であり、最適化により難読化されています。このため、リスクは、競合他社がコードを逆アセンブルして再利用する場合と同程度です。それでもやはり、アプリでカスタムモデルを使用する前に、このリスクを認識しておく必要があります。

Android API レベル 21(Lollipop)以降では、モデルは自動バックアップから除外されるディレクトリにダウンロードされます。

Android API レベル 20 以前では、モデルはアプリ専用の内部ストレージ内の com.google.firebase.ml.custom.models というディレクトリにダウンロードされます。BackupAgent を使用したファイルのバックアップを有効にした場合は、このディレクトリを除外できます。

モデルを Firebase でホストする

TensorFlow Lite モデルを Firebase でホストするには:

  1. Firebase コンソールの [ML Kit] セクションで、[カスタム] タブをクリックします。
  2. [カスタムモデルを追加](または [別のモデルを追加])をクリックします。
  3. Firebase プロジェクトでモデルを識別するための名前を指定し、.tflite ファイルをアップロードします。
  4. アプリのマニフェストで、INTERNET 権限が必要であることを宣言します。
    <uses-permission android:name="android.permission.INTERNET" />
    

Firebase プロジェクトにカスタムモデルを追加した後は、指定した名前を使用してアプリ内でモデルを参照できます。モデルの新しい .tflite ファイルはいつでもアップロードできます。アプリは、次回の起動時に新しいモデルをダウンロードして使い始めます。アプリがモデルを更新するために必要な端末の条件を定義できます(以下を参照)。

モデルをローカルで使用可能にする

TensorFlow Lite モデルをローカルで使用可能にするには、モデルをアプリにバンドルするか、各自のサーバーからアプリにモデルをダウンロードします。

TensorFlow Lite モデルをアプリにバンドルするには、アプリの assets/ フォルダに .tflite ファイルをコピーします。場合によっては、先にこのフォルダを作成する必要があります。作成するには、app/ フォルダを右クリックし、[新規] > [フォルダ] > [アセット フォルダ] の順にクリックします。

次に、プロジェクトの build.gradle ファイルに次の情報を追加します。

android {

    // ...

    aaptOptions {
        noCompress "tflite"
    }
}

.tflite ファイルがアプリ パッケージに含められ、ML Kit で生アセットとして使用可能になります。

独自のサーバーにモデルをホストする場合は、アプリの中で適切なタイミングでモデルをローカル ストレージにダウンロードできます。その後、モデルはローカル ファイルとして ML Kit で使用可能になります。

モデルを読み込む

TensorFlow Lite モデルを推論に使用するには、最初に .tflite ファイルの場所を指定します。

Firebase でモデルをホストする場合は、FirebaseCloudModelSource オブジェクトを作成します。その際に、モデルをアップロードしたときに割り当てた名前と、ML Kit が最初にモデルをダウンロードするための条件、および更新が利用可能になった場合にそれをダウンロードするための条件を指定します。

FirebaseModelDownloadConditions.Builder conditionsBuilder =
        new FirebaseModelDownloadConditions.Builder().requireWifi();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    // Enable advanced conditions on Android Nougat and newer.
    conditionsBuilder = conditionsBuilder
            .requireCharging()
            .requireDeviceIdle();
}
FirebaseModelDownloadConditions conditions = conditionsBuilder.build();

// Build a FirebaseCloudModelSource object by specifying the name you assigned the model
// when you uploaded it in the Firebase console.
FirebaseCloudModelSource cloudSource = new FirebaseCloudModelSource.Builder("my_cloud_model")
        .enableModelUpdates(true)
        .setInitialDownloadConditions(conditions)
        .setUpdatesDownloadConditions(conditions)
        .build();
FirebaseModelManager.getInstance().registerCloudModelSource(cloudSource);

アプリにモデルをバンドルする場合、または実行時に独自のホストからモデルをダウンロードする場合は、FirebaseLocalModelSource オブジェクトを作成します。その際に、.tflite モデルのファイル名と、ファイルが生アセットであるか(バンドル)またはローカル ストレージにあるか(実行時にダウンロード)を指定します。

FirebaseLocalModelSource localSource = new FirebaseLocalModelSource.Builder("my_local_model")
        .setAssetFilePath("mymodel.tflite")  // Or setFilePath if you downloaded from your host
        .build();
FirebaseModelManager.getInstance().registerLocalModelSource(localSource);

次に、Cloud ソース、ローカルソース、またはその両方の名前を指定して FirebaseModelOptions オブジェクトを作成し、それを使用して FirebaseModelInterpreter のインスタンスを取得します。

FirebaseModelOptions options = new FirebaseModelOptions.Builder()
        .setCloudModelName("my_cloud_model")
        .setLocalModelName("my_local_model")
        .build();
FirebaseModelInterpreter firebaseInterpreter =
        FirebaseModelInterpreter.getInstance(options);

クラウドモデルとローカルモデルの両方のソースを指定すると、モデル インタープリタはクラウドモデルが使用できる場合はそれを使用し、使用できない場合はローカルモデルを使用します。

モデルの入力と出力を指定する

次に、FirebaseModelInputOutputOptions オブジェクトを作成して、モデルの入力と出力の形式を指定する必要があります。

TensorFlow Lite モデルは、1 つ以上の多次元配列を入力として受け取り、出力として生成します。これらの配列には、byteintlongfloat 値のいずれかが含まれます。モデルで使用する配列の数と次元(「シェイプ」)で ML キットを構成する必要があります。

たとえば、画像分類モデルは、1 つの 640 x 480 トゥルーカラー(24 ビット)画像を表す 1 x 640 x 480 x 3 バイトの配列を入力として受け取り、画像がモデルによって予測される 1000 カテゴリのいずれかのメンバーである確率をそれぞれ表す 1000 個の float 値のリストを出力として生成します。

FirebaseModelInputOutputOptions inputOutputOptions =
    new FirebaseModelInputOutputOptions.Builder()
        .setInputFormat(0, FirebaseModelDataType.BYTE, new int[]{1, 640, 480, 3})
        .setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 1000})
        .build();

入力データの推論を行う

最後に、モデルを使用して推論を実行するには、モデル入力を使用して FirebaseModelInputs オブジェクトを作成し、そのオブジェクトとモデルの入出力指定をモデル インタープリタrun メソッドに渡します。

byte[][][][] input = new byte[1][640][480][3];
input = getYourInputData();
FirebaseModelInputs inputs = new FirebaseModelInputs.Builder()
    .add(input)  // add() as many input arrays as your model requires
    .build();
Task<FirebaseModelOutputs> result =
    firebaseInterpreter.run(inputs, inputOutputOptions)
        .addOnSuccessListener(
          new OnSuccessListener<FirebaseModelOutputs>() {
            @Override
            public void onSuccess(FirebaseModelOutputs result) {
              // ...
            }
          })
        .addOnFailureListener(
          new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
              // Task failed with an exception
              // ...
            }
          });

成功リスナーに渡されたオブジェクトの getOutput() メソッドを呼び出すことで、出力を取得できます。次に例を示します。

float[][] output = result.<float[][]>getOutput(0);
float[] probabilities = output[0];

出力の使い方は、使用しているモデルによって異なります。たとえば、分類を実行する場合は、次のステップとして結果のインデックスを、それらが表すラベルにマッピングできます。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。