Buka konsol

Menggunakan model TensorFlow Lite untuk inferensi dengan ML Kit di Android

Anda dapat menggunakan Kit ML untuk melakukan perangkat inferensi-dalam-perangkat dengan model TensorFlow Lite .

API ini membutuhkan SDK Android level 16 (Jelly Bean) atau yang lebih baru.

Lihat sampel quickstart ML Kit di GitHub untuk mengetahui contoh penggunaan API ini, atau cobalah codelab.

Sebelum memulai

  1. Tambahkan Firebase ke project Android jika Anda belum melakukannya.
  2. Pada file build.gradle level project, pastikan untuk menyertakan repositori Maven Google di bagian buildscript dan allprojects Anda.
  3. Tambahkan dependensi untuk library Android ML Kit ke file Gradle modul (tingkat aplikasi) (biasanya app/build.gradle):
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-model-interpreter:21.0.0'
    }
    
  4. Konversikan model TensorFlow yang ingin Anda gunakan ke dalam format TensorFlow Lite. Lihat TOCO: TensorFlow Lite Konverter Optimalisasi.

Menghosting atau membuat paket model Anda

Sebelum dapat menggunakan model TensorFlow Lite untuk inferensi di aplikasi, Anda harus membuat model tersedia untuk ML Kit. ML Kit dapat menggunakan model TensorFlow Lite yang dihosting dari jarak jauh menggunakan Firebase, dipaketkan dengan biner aplikasi, atau keduanya.

Dengan menghosting model di Firebase, Anda dapat mengupdate model tanpa merilis versi baru aplikasi, dan Anda dapat menggunakan Remote Config serta Pengujian A/B untuk menerapkan berbagai model secara dinamis ke kumpulan pengguna yang berbeda.

Jika Anda memilih untuk hanya menyediakan model dengan menghostingnya dengan Firebase, dan tidak memaketkannya dengan aplikasi Anda, Anda dapat mengurangi ukuran download awal aplikasi Anda. Namun, perlu diingat jika model tidak dipaketkan dengan aplikasi Anda, fungsi yang terkait dengan model tidak akan tersedia hingga aplikasi Anda mendownload model untuk pertama kalinya.

Dengan memaketkan model dengan aplikasi, Anda dapat memastikan bahwa fitur ML pada aplikasi Anda masih berfungsi jika model yang dihosting Firebase tidak tersedia.

Menghosting model di Firebase

Untuk menghosting model TensorFlow Lite di Firebase:

  1. Di bagian ML Kit pada Firebase console, klik tab Kustom.
  2. Klik Tambahkan model kustom (atau Tambahkan model lain).
  3. Tentukan nama yang akan digunakan untuk mengidentifikasi model Anda di project Firebase, lalu upload file model TensorFlow Lite (biasanya diakhiri dengan .tflite atau .lite ).
  4. Di manifes aplikasi Anda, nyatakan bahwa izin INTERNET diperlukan:
    <uses-permission android:name="android.permission.INTERNET" />
    

Setelah menambahkan model kustom ke project Firebase, Anda dapat mereferensikan model tersebut di aplikasi menggunakan nama yang Anda tentukan. Anda dapat mengupload file model TensorFlow Lite baru kapan saja untuk sebuah model, dan aplikasi Anda akan mendownload model baru itu dan mulai menggunakannya begitu aplikasi dimulai ulang. Anda dapat menentukan kondisi perangkat yang diperlukan aplikasi untuk mencoba mengupdate model (lihat di bawah ini).

Paketkan model dengan aplikasi

Untuk membuat paket model TensorFlow Lite dengan aplikasi Anda, salin file model (biasanya diakhiri dengan .tflite atau .lite) ke folder assets/ aplikasi Anda. (Anda mungkin perlu membuat folder terlebih dahulu dengan mengklik kanan folder app/, lalu mengklik Baru > Folder > Folder Aset.)

Kemudian, tambahkan baris berikut ke file build.gradle aplikasi Anda untuk memastikan Gradle tidak mengompresi model saat membuat aplikasi:

android {

    // ...

    aaptOptions {
        noCompress "tflite"  // Your model's file extension: "tflite", "lite", etc.
    }
}

File model akan dimasukkan ke dalam paket aplikasi dan tersedia untuk ML Kit sebagai aset mentah.

Memuat model

Untuk menggunakan model TensorFlow Lite Anda di aplikasi, pertama-tama konfigurasikan ML Kit dengan lokasi tempat model Anda tersedia: menggunakan Firebase dari jarak jauh, di penyimpanan lokal, atau keduanya. Jika Anda menetapkan model lokal dan jarak jauh, ML Kit akan menggunakan model jarak jauh jika tersedia, dan kembali ke model yang disimpan secara lokal jika model jarak jauh tidak tersedia.

Mengonfigurasi model yang dihosting oleh Firebase

Jika Anda menghosting model dengan Firebase, buat objek FirebaseRemoteModel dengan menentukan nama yang Anda tetapkan untuk model tersebut ketika menguploadnya, serta kondisi kapan ML Kit harus mendownload model di awal dan saat update tersedia.

Java

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 remote model source object by specifying the name you assigned the model
// when you uploaded it in the Firebase console.
FirebaseRemoteModel cloudSource = new FirebaseRemoteModel.Builder("my_cloud_model")
        .enableModelUpdates(true)
        .setInitialDownloadConditions(conditions)
        .setUpdatesDownloadConditions(conditions)
        .build();
FirebaseModelManager.getInstance().registerRemoteModel(cloudSource);

Kotlin

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

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

Mengonfigurasi model lokal

Jika Anda memaketkan model dengan aplikasi, buat objek FirebaseLocalModel dengan menentukan nama file model TensorFlow Lite dan menetapkan nama pada model yang akan digunakan pada langkah berikutnya.

Java

FirebaseLocalModel localSource =
        new FirebaseLocalModel.Builder("my_local_model")  // Assign a name to this model
                .setAssetFilePath("my_model.tflite")
                .build();
FirebaseModelManager.getInstance().registerLocalModel(localSource);

Kotlin

val localSource = FirebaseLocalModel.Builder("my_local_model") // Assign a name to this model
        .setAssetFilePath("my_model.tflite")
        .build()
FirebaseModelManager.getInstance().registerLocalModel(localSource)

Membuat penafsir dari model Anda

Setelah Anda mengonfigurasi lokasi model, buat objek FirebaseModelOptions dengan nama model jarak jauh, model lokal, atau keduanya, dan gunakan untuk mendapatkan instance FirebaseModelInterpreter:

Java

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

Kotlin

val options = FirebaseModelOptions.Builder()
        .setRemoteModelName("my_cloud_model")
        .setLocalModelName("my_local_model")
        .build()
val interpreter = FirebaseModelInterpreter.getInstance(options)

Memastikan model tersedia di perangkat

Direkomendasikan: Jika Anda tidak mengonfigurasi model yang dipaket secara lokal, pastikan model jarak jauh telah didownload ke perangkat.

Ketika Anda menjalankan model yang dihosting dari jarak jauh, jika model tersebut belum tersedia di perangkat, panggilan akan gagal dan model didownload secara otomatis ke perangkat di latar belakang. Ketika download selesai, Anda dapat menjalankan model dengan sukses.

Jika Anda ingin menangani tugas mendownload model secara lebih eksplisit, Anda dapat memulai tugas tersebut dan memeriksa statusnya dengan memanggil downloadRemoteModelIfNeeded():

Java

FirebaseModelManager.getInstance().downloadRemoteModelIfNeeded(remoteModel)
        .addOnSuccessListener(
            new OnSuccessListener<Void>() {
              @Override
              public void onSuccess() {
                // Model downloaded successfully. Okay to use the model.
              }
            })
        .addOnFailureListener(
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Model couldn’t be downloaded or other internal error.
                // ...
              }
            });

Kotlin

FirebaseModelManager.getInstance().downloadRemoteModelIfNeeded(remoteModel)
        .addOnSuccessListener {
            // Model downloaded successfully. Okay to use the model.
        }
        .addOnFailureListener {
            // Model couldn’t be downloaded or other internal error.
            // ...
        }

Metode downloadRemoteModelIfNeeded() mulai mendownload model jika perlu, dan memanggil pemroses yang berhasil ketika download selesai. Jika model sudah tersedia, metode ini segera memanggil pemroses yang berhasil.

Menentukan input dan output model

Selanjutnya, konfigurasikan format input dan output penafsir model.

Model TensorFlow Lite mengambil satu atau beberapa array multidimensi sebagai input dan menghasilkannya sebagai output. Array ini berisi nilai byte, int, long, atau float. Anda harus mengonfigurasi ML Kit dengan jumlah dan dimensi ("bentuk") array yang digunakan oleh model Anda.

Jika Anda tidak tahu bentuk dan tipe data dari input dan output model, Anda dapat menggunakan penafsir TensorFlow Lite Python untuk memeriksa model. Misalnya:

import tensorflow as tf

interpreter = tf.lite.Interpreter(model_path="my_model.tflite")
interpreter.allocate_tensors()

# Print input shape and type
print(interpreter.get_input_details()[0]['shape'])  # Example: [1 224 224 3]
print(interpreter.get_input_details()[0]['dtype'])  # Example: <class 'numpy.float32'>

# Print output shape and type
print(interpreter.get_output_details()[0]['shape'])  # Example: [1 1000]
print(interpreter.get_output_details()[0]['dtype'])  # Example: <class 'numpy.float32'>

Setelah menentukan format input dan output model, konfigurasikan penafsir model aplikasi Anda dengan membuat objek FirebaseModelInputOutputOptions.

Sebagai contoh, model klasifikasi gambar floating-point mungkin akan mengambil array Nx224x224x3 berisi nilai float sebagai input, yang mewakili sekumpulan gambar N 224x224 tiga saluran (RGB) dan menghasilkan output berupa daftar 1.000 nilai float. Setiap nilai ini mewakili probabilitas bahwa gambar tersebut merupakan anggota dari salah satu dari 1.000 kategori yang diprediksi oleh model.

Untuk model seperti itu, Anda akan mengonfigurasi input dan output penafsir model, seperti yang ditunjukkan di bawah ini:

Java

FirebaseModelInputOutputOptions inputOutputOptions =
        new FirebaseModelInputOutputOptions.Builder()
                .setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 224, 224, 3})
                .setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 5})
                .build();

Kotlin

val inputOutputOptions = FirebaseModelInputOutputOptions.Builder()
        .setInputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 224, 224, 3))
        .setOutputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 5))
        .build()

Melakukan inferensi pada data masukan

Terakhir, untuk melakukan inferensi menggunakan model, dapatkan data input Anda, dan jalankan transformasi pada data yang diperlukan untuk mendapatkan array input dari bentuk yang tepat untuk model Anda.

Misalnya, jika Anda memiliki model klasifikasi gambar dengan bentuk input dari nilai titik apung [1 224 224 3], Anda bisa menghasilkan array input dari objek Bitmap seperti yang ditunjukkan dalam contoh berikut:

Java

Bitmap bitmap = getYourInputImage();
bitmap = Bitmap.createScaledBitmap(bitmap, 224, 224, true);

int batchNum = 0;
float[][][][] input = new float[1][224][224][3];
for (int x = 0; x < 224; x++) {
    for (int y = 0; y < 224; y++) {
        int pixel = bitmap.getPixel(x, y);
        // Normalize channel values to [-1.0, 1.0]. This requirement varies by
        // model. For example, some models might require values to be normalized
        // to the range [0.0, 1.0] instead.
        input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 128.0f;
        input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 128.0f;
        input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 128.0f;
    }
}

Kotlin

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)

val batchNum = 0
val input = Array(1) { Array(224) { Array(224) { FloatArray(3) } } }
for (x in 0..223) {
    for (y in 0..223) {
        val pixel = bitmap.getPixel(x, y)
        // Normalize channel values to [-1.0, 1.0]. This requirement varies by
        // model. For example, some models might require values to be normalized
        // to the range [0.0, 1.0] instead.
        input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 255.0f
        input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 255.0f
        input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 255.0f
    }
}

Kemudian, buat objek FirebaseModelInputs dengan data input Anda, lalu teruskan objek tersebut bersama dengan spesifikasi input dan output model ke metode run penafsir model:

Java

FirebaseModelInputs inputs = new FirebaseModelInputs.Builder()
        .add(input)  // add() as many input arrays as your model requires
        .build();
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
                        // ...
                    }
                });

Kotlin

val inputs = FirebaseModelInputs.Builder()
        .add(input) // add() as many input arrays as your model requires
        .build()
firebaseInterpreter.run(inputs, inputOutputOptions)
        .addOnSuccessListener { result ->
            // ...
        }
        .addOnFailureListener(
                object : OnFailureListener {
                    override fun onFailure(e: Exception) {
                        // Task failed with an exception
                        // ...
                    }
                })

Jika panggilan berhasil, Anda bisa mendapatkan output dengan memanggil metode getOutput() dari objek yang diteruskan ke listener yang berhasil. Misalnya:

Java

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

Kotlin

val output = result.getOutput<Array<FloatArray>>(0)
val probabilities = output[0]

Cara penggunaan output bergantung pada model yang Anda gunakan.

Misalnya, jika Anda melakukan klasifikasi, sebagai langkah berikutnya, Anda mungkin dapat memetakan indeks hasil ke label yang diwakilinya.

Java

BufferedReader reader = new BufferedReader(
        new InputStreamReader(getAssets().open("retrained_labels.txt")));
for (int i = 0; i < probabilities.length; i++) {
    String label = reader.readLine();
    Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i]));
}

Kotlin

val reader = BufferedReader(
        InputStreamReader(assets.open("retrained_labels.txt")))
for (i in probabilities.indices) {
    val label = reader.readLine()
    Log.i("MLKit", String.format("%s: %1.4f", label, probabilities[i]))
}

Lampiran: Keamanan model

Apa pun cara Anda dalam menyediakan model TensorFlow Lite untuk ML Kit, ML Kit akan menyimpannya dalam format protobuf serial standar di penyimpanan lokal.

Secara teori, ini artinya siapa saja dapat menyalin model Anda. Namun, dalam praktiknya, sebagian besar model bersifat khusus aplikasi dan dikaburkan oleh pengoptimalan sehingga risikonya serupa dengan jika pesaing membongkar dan menggunakan kembali kode Anda. Meskipun demikian, Anda harus menyadari risiko ini sebelum menggunakan model kustom di aplikasi Anda.

Pada Android API level 21 (Lollipop) dan yang lebih baru, model didownload ke direktori yang dikecualikan dari backup otomatis.

Pada Android API level 20 dan yang lebih lama, model didownload ke direktori bernama com.google.firebase.ml.custom.models di penyimpanan internal pribadi aplikasi. Jika mengaktifkan cadangan file menggunakan BackupAgent, Anda dapat memilih untuk tidak menyertakan direktori ini.