Android'de ML Kit ile çıkarım yapmak için TensorFlow Lite modelini kullanma

TensorFlow Lite modeliyle cihaz üzerinde çıkarım gerçekleştirmek için ML Kit'i kullanabilirsiniz.

Bu API, Android SDK seviye 16 (Jelly Bean) veya daha yenisini gerektirir.

Sen başlamadan önce

  1. Henüz yapmadıysanız Android projenize Firebase'i ekleyin .
  2. ML Kit Android kitaplıklarının bağımlılıklarını modülünüze (uygulama düzeyinde) Gradle dosyasına ekleyin (genellikle app/build.gradle ):
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-model-interpreter:22.0.3'
    }
    
  3. Kullanmak istediğiniz TensorFlow modelini TensorFlow Lite formatına dönüştürün. Bkz. TOCO: TensorFlow Lite Optimize Edici Dönüştürücü .

Modelinizi barındırın veya paketleyin

Uygulamanızda çıkarım amacıyla bir TensorFlow Lite modelini kullanabilmeniz için öncelikle modeli ML Kit'in kullanımına sunmanız gerekir. ML Kit, Firebase kullanılarak uzaktan barındırılan, uygulama ikili dosyasıyla birlikte verilen TensorFlow Lite modellerini veya her ikisini birden kullanabilir.

Firebase'de bir model barındırarak, yeni bir uygulama sürümü yayınlamadan modeli güncelleyebilir ve farklı kullanıcı gruplarına farklı modelleri dinamik olarak sunmak için Uzaktan Yapılandırma ve A/B Testini kullanabilirsiniz.

Modeli yalnızca Firebase'de barındırarak sağlamayı ve uygulamanızla birlikte paketlememeyi seçerseniz uygulamanızın ilk indirme boyutunu azaltabilirsiniz. Ancak, model uygulamanızla birlikte paketlenmemişse, uygulamanız modeli ilk kez indirene kadar modelle ilgili herhangi bir işlevin kullanılamayacağını unutmayın.

Modelinizi uygulamanızla birlikte paketleyerek, Firebase tarafından barındırılan model mevcut olmadığında uygulamanızın makine öğrenimi özelliklerinin çalışmaya devam etmesini sağlayabilirsiniz.

Firebase'de modelleri barındırın

TensorFlow Lite modelinizi Firebase'de barındırmak için:

  1. Firebase konsolunun ML Kiti bölümünde Özel sekmesini tıklayın.
  2. Özel model ekle'yi (veya Başka bir model ekle ) tıklayın.
  3. Firebase projenizde modelinizi tanımlamak için kullanılacak bir ad belirtin ve ardından TensorFlow Lite model dosyasını yükleyin (genellikle .tflite veya .lite ile biter).
  4. Uygulamanızın manifest dosyasında İNTERNET izninin gerekli olduğunu belirtin:
    <uses-permission android:name="android.permission.INTERNET" />
    

Firebase projenize özel bir model ekledikten sonra, belirttiğiniz adı kullanarak uygulamalarınızda modele referans verebilirsiniz. İstediğiniz zaman yeni bir TensorFlow Lite modeli yükleyebilirsiniz; uygulamanız yeni modeli indirecek ve uygulama bir sonraki yeniden başlatıldığında kullanmaya başlayacaktır. Uygulamanızın modeli güncellemeye çalışması için gereken cihaz koşullarını tanımlayabilirsiniz (aşağıya bakın).

Modelleri bir uygulamayla paketleyin

TensorFlow Lite modelinizi uygulamanızla birlikte paketlemek için model dosyasını (genellikle .tflite veya .lite ile biter) uygulamanızın assets/ klasörüne kopyalayın. (Önce app/ klasöre sağ tıklayıp ardından Yeni > Klasör > Varlıklar Klasörü öğesine tıklayarak klasörü oluşturmanız gerekebilir.)

Ardından, Gradle'ın uygulamayı oluştururken modelleri sıkıştırmadığından emin olmak için uygulamanızın build.gradle dosyasına aşağıdakileri ekleyin:

android {

    // ...

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

Model dosyası uygulama paketine dahil edilecek ve ML Kit'e ham varlık olarak sunulacak.

Modeli yükle

TensorFlow Lite modelinizi uygulamanızda kullanmak için öncelikle ML Kit'i modelinizin mevcut olduğu konumlarla yapılandırın: Firebase'i kullanarak uzaktan, yerel depolamada veya her ikisinde birden. Hem yerel hem de uzak modeli belirtirseniz, varsa uzak modeli kullanabilir, uzak model yoksa yerel olarak depolanan modele geri dönebilirsiniz.

Firebase tarafından barındırılan bir modeli yapılandırma

Modelinizi Firebase'de barındırdıysanız, modeli yüklediğinizde atadığınız adı belirterek bir FirebaseCustomRemoteModel nesnesi oluşturun:

Java

FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

Kotlin+KTX

val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()

Ardından, indirmeye izin vermek istediğiniz koşulları belirterek model indirme görevini başlatın. Model cihazda yoksa veya modelin daha yeni bir sürümü mevcutsa görev, modeli Firebase'den eşzamansız olarak indirir:

Java

FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions.Builder()
        .requireWifi()
        .build();
FirebaseModelManager.getInstance().download(remoteModel, conditions)
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                // Success.
            }
        });

Kotlin+KTX

val conditions = FirebaseModelDownloadConditions.Builder()
    .requireWifi()
    .build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
    .addOnCompleteListener {
        // Success.
    }

Çoğu uygulama, indirme görevini kendi başlatma kodunda başlatır, ancak bunu, modeli kullanmanız gerekmeden önce herhangi bir noktada yapabilirsiniz.

Yerel bir model yapılandırma

Modeli uygulamanızla birlikte paketlediyseniz TensorFlow Lite modelinin dosya adını belirterek bir FirebaseCustomLocalModel nesnesi oluşturun:

Java

FirebaseCustomLocalModel localModel = new FirebaseCustomLocalModel.Builder()
        .setAssetFilePath("your_model.tflite")
        .build();

Kotlin+KTX

val localModel = FirebaseCustomLocalModel.Builder()
    .setAssetFilePath("your_model.tflite")
    .build()

Modelinizden bir tercüman oluşturun

Model kaynaklarınızı yapılandırdıktan sonra bunlardan birinden bir FirebaseModelInterpreter nesnesi oluşturun.

Yalnızca yerel olarak paketlenmiş bir modeliniz varsa FirebaseCustomLocalModel nesnenizden bir tercüman oluşturmanız yeterlidir:

Java

FirebaseModelInterpreter interpreter;
try {
    FirebaseModelInterpreterOptions options =
            new FirebaseModelInterpreterOptions.Builder(localModel).build();
    interpreter = FirebaseModelInterpreter.getInstance(options);
} catch (FirebaseMLException e) {
    // ...
}

Kotlin+KTX

val options = FirebaseModelInterpreterOptions.Builder(localModel).build()
val interpreter = FirebaseModelInterpreter.getInstance(options)

Uzaktan barındırılan bir modeliniz varsa, çalıştırmadan önce indirilip indirilmediğini kontrol etmeniz gerekecektir. Model yöneticisinin isModelDownloaded() yöntemini kullanarak model indirme görevinin durumunu kontrol edebilirsiniz.

Her ne kadar yorumlayıcıyı çalıştırmadan önce bunu yalnızca onaylamanız gerekse de, hem uzaktan barındırılan bir modeliniz hem de yerel olarak paketlenmiş bir modeliniz varsa, model yorumlayıcısını başlatırken bu kontrolü gerçekleştirmek mantıklı olabilir: eğer uzak modelden bir yorumlayıcı oluşturun indirilmiştir ve aksi takdirde yerel modelden indirilmiştir.

Java

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
                FirebaseModelInterpreterOptions options;
                if (isDownloaded) {
                    options = new FirebaseModelInterpreterOptions.Builder(remoteModel).build();
                } else {
                    options = new FirebaseModelInterpreterOptions.Builder(localModel).build();
                }
                FirebaseModelInterpreter interpreter = FirebaseModelInterpreter.getInstance(options);
                // ...
            }
        });

Kotlin+KTX

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
    .addOnSuccessListener { isDownloaded -> 
    val options =
        if (isDownloaded) {
            FirebaseModelInterpreterOptions.Builder(remoteModel).build()
        } else {
            FirebaseModelInterpreterOptions.Builder(localModel).build()
        }
    val interpreter = FirebaseModelInterpreter.getInstance(options)
}

Yalnızca uzaktan barındırılan bir modeliniz varsa, modelin indirildiğini onaylayana kadar modelle ilgili işlevleri (örneğin, kullanıcı arayüzünüzün grileştirilmesi veya bir kısmının gizlenmesi) devre dışı bırakmalısınız. Bunu, model yöneticisinin download() yöntemine bir dinleyici ekleyerek yapabilirsiniz:

Java

FirebaseModelManager.getInstance().download(remoteModel, conditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void v) {
              // Download complete. Depending on your app, you could enable
              // the ML feature, or switch from the local model to the remote
              // model, etc.
            }
        });

Kotlin+KTX

FirebaseModelManager.getInstance().download(remoteModel, conditions)
    .addOnCompleteListener {
        // Download complete. Depending on your app, you could enable the ML
        // feature, or switch from the local model to the remote model, etc.
    }

Modelin giriş ve çıkışını belirtin

Daha sonra model yorumlayıcının giriş ve çıkış formatlarını yapılandırın.

TensorFlow Lite modeli girdi olarak alır ve çıktı olarak bir veya daha fazla çok boyutlu dizi üretir. Bu diziler byte , int , long veya float değerlerini içerir. ML Kit'i, modelinizin kullandığı dizilerin sayısı ve boyutları ("şekli") ile yapılandırmanız gerekir.

Modelinizin giriş ve çıkışının şeklini ve veri türünü bilmiyorsanız modelinizi incelemek için TensorFlow Lite Python yorumlayıcısını kullanabilirsiniz. Örneğin:

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'>

Modelinizin giriş ve çıkış biçimini belirledikten sonra bir FirebaseModelInputOutputOptions nesnesi oluşturarak uygulamanızın model yorumlayıcısını yapılandırabilirsiniz.

Örneğin, bir kayan noktalı görüntü sınıflandırma modeli, N adet 224x224 üç kanallı (RGB) görüntü grubunu temsil eden N x224x224x3 float değerleri dizisini girdi olarak alabilir ve çıktı olarak, her biri aşağıdakileri temsil eden 1000 float değeri içeren bir liste üretebilir. görüntünün modelin öngördüğü 1000 kategoriden birinin üyesi olma olasılığı.

Böyle bir model için model yorumlayıcısının giriş ve çıkışını aşağıda gösterildiği gibi yapılandırırsınız:

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+KTX

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

Giriş verileri üzerinde çıkarım gerçekleştirin

Son olarak, modeli kullanarak çıkarım yapmak için giriş verilerinizi alın ve modeliniz için doğru şekle sahip bir giriş dizisi elde etmek amacıyla veriler üzerinde gerekli tüm dönüşümleri gerçekleştirin.

Örneğin, [1 224 224 3] kayan nokta değerlerinin giriş şekline sahip bir görüntü sınıflandırma modeliniz varsa, aşağıdaki örnekte gösterildiği gibi bir Bitmap nesnesinden bir giriş dizisi oluşturabilirsiniz:

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+KTX

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
    }
}

Ardından, giriş verilerinizle bir FirebaseModelInputs nesnesi oluşturun ve onu ve modelin giriş ve çıkış özelliklerini model yorumlayıcısının run yöntemine iletin:

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+KTX

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

Çağrı başarılı olursa başarı dinleyicisine iletilen nesnenin getOutput() yöntemini çağırarak çıktıyı alabilirsiniz. Örneğin:

Java

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

Kotlin+KTX

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

Çıktıyı nasıl kullanacağınız kullandığınız modele bağlıdır.

Örneğin, sınıflandırma yapıyorsanız bir sonraki adım olarak sonucun indekslerini temsil ettikleri etiketlerle eşleştirebilirsiniz:

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+KTX

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]))
}

Ek: Model güvenliği

TensorFlow Lite modellerinizi ML Kit'e nasıl sunduğunuzdan bağımsız olarak, ML Kit bunları yerel depolamada standart serileştirilmiş protobuf formatında saklar.

Teorik olarak bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Bununla birlikte, pratikte çoğu model uygulamaya o kadar özeldir ve optimizasyonlar nedeniyle karartılmıştır ki, risk, rakiplerinizin kodunuzu parçalara ayırıp yeniden kullanması ile benzerdir. Ancak uygulamanızda özel bir model kullanmadan önce bu riskin farkında olmalısınız.

Android API düzeyi 21 (Lollipop) ve daha yeni sürümlerde model, otomatik yedeklemenin dışında bırakılan bir dizine indirilir.

Android API düzeyi 20 ve daha eski sürümlerde model, uygulamaya özel dahili depolama alanındaki com.google.firebase.ml.custom.models adlı dizine indirilir. BackupAgent kullanarak dosya yedeklemeyi etkinleştirdiyseniz bu dizini hariç tutmayı seçebilirsiniz.