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

Android Kit'i kullanarak cihaz üzerinde çıkarım yapmak için TensorFlow Lite modeli.

Bu API, Android SDK düzey 16 (Jelly Bean) veya daha yeni bir sürüm gerektirir.

Başlamadan önce

  1. Henüz yapmadıysanız Firebase'i Android projenize ekleyin.
  2. Modülünüze ML Kit Android kitaplıkları için bağımlılıkları ekleyin (uygulama düzeyinde) Gradle dosyası (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 biçimine dönüştürün. Görüntüleyin TOCO: TensorFlow Lite Dönüşüm Optimize Edici.

Modelinizi barındırın veya paketleyin

Uygulamanızda çıkarım için TensorFlow Lite modelini kullanmadan önce modeli ML Kit'te kullanılabilir hale getirmelidir. ML Kit, TensorFlow Lite'ı kullanabilir Firebase kullanılarak uzaktan barındırılan, uygulama ikili programıyla paket halinde sunulan veya her iki model de kullanılabilir.

Firebase'de bir model barındırarak bir model yayınlamadan güncelleyebilirsiniz. ve Remote Config ve A/B Testing özelliklerini kullanarak Farklı kullanıcı gruplarına dinamik olarak farklı modeller sunar.

Modeli Firebase'de barındırarak değil, yalnızca Firebase'de barındırarak sağlamayı seçerseniz uygulamanızla birlikte paket haline getirirseniz uygulamanızın başlangıçtaki indirme boyutunu küçültebilirsiniz. Bununla birlikte, modelin uygulamanızla birlikte paket halinde olmadığı durumlarda, uygulamanız, uygulamanızı indirene kadar modelle ilgili işlevleri ilk kez devreye giriyor.

Modelinizi uygulamanızla paket haline getirerek uygulamanızın makine öğrenimi özelliklerinin etkin olmasını sağlayabilirsiniz. Firebase tarafından barındırılan model kullanılamadığında çalışmaya devam eder.

Firebase'de modelleri barındırma

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

  1. Firebase konsolunun Makine Öğrenimi Kiti bölümünde Özel sekmesi.
  2. Özel model ekle (veya Başka bir model ekle) seçeneğini tıklayın.
  3. Firebase'inizde modelinizi tanımlamak için kullanılacak bir ad belirtin açın, ardından TensorFlow Lite model dosyasını yükleyin (genellikle .tflite veya .lite).
  4. Uygulamanızın manifest dosyasında, INTERNET izninin gerekli olduğunu beyan edin:
    <uses-permission android:name="android.permission.INTERNET" />

Firebase projenize özel model ekledikten sonra, modeliniz olmalıdır. İstediğiniz zaman yeni bir TensorFlow Lite modelini çıkarırsanız uygulamanız yeni modeli indirir ve Uygulama yeniden başlatıldığında bunu kullanmaya başlayabilirsiniz. Cihazı tanımlayabilirsiniz. uygulamanızın modeli güncellemeyi denemesi için gereken koşullar (aşağıya bakın).

Modelleri uygulama ile paketleme

TensorFlow Lite modelinizi uygulamanızla paketlemek için model dosyasını (genellikle .tflite veya .lite ile biten) uygulamanızın assets/ klasörüne kopyalayın. ( için; önce app/ klasörünü sağ tıklayıp ardından klasörü tıklayarak klasörü oluşturun. Yeni > Klasör > Öğeler Klasörü'nü tıklayın.)

Ardından aşağıdaki kodu uygulamanızın build.gradle dosyasına ekleyerek Gradle'ın uygulamayı oluştururken modelleri sıkıştırmaz:

android {

    // ...

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

Model dosyası uygulama paketine dahil edilir ve ML Kit tarafından kullanılabilir işlenmemiş bir öğe olarak görebiliriz.

Modeli yükleme

TensorFlow Lite modelinizi uygulamanızda kullanmak için öncelikle ML Kit'i modelinizin mevcut olduğu konumlar: Firebase'i uzaktan kullanma, ya da her ikisi birden olabilir. Hem yerel hem de uzak model belirtirseniz kullanılabiliyorsa uzak modeli kullanabilir ve yerel olarak depolanan modelle ilişkilidir.

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

Modelinizi Firebase ile barındırdıysanız bir FirebaseCustomRemoteModel oluşturun nesnesini tanımlayın, modeli yüklerken atadığınız adı belirtin:

Java

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

Kotlin+KTX

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

Ardından, model indirme görevinizi başlatmak için model indirmenizi istediğiniz koşulları indirmeye izin vermek istiyorsunuz. Model cihazda yoksa veya sürümü kullanılabiliyorsa görev, yeni bir sürümün yüklü olduğu modeliniz:

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

Birçok uygulama, indirme görevini başlatma kodunda başlatır ancak bu nedenle, herhangi bir noktada modeli kullanabilirsiniz.

Yerel model yapılandırma

Modeli uygulamanızla paketlediyseniz bir FirebaseCustomLocalModel oluşturun nesnesini tanımlayın:

Java

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

Kotlin+KTX

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

Modelinizden çevirmen oluşturma

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

Yalnızca yerel olarak paketlenmiş bir modeliniz varsa FirebaseCustomLocalModel nesne:

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 bu modelin indiremezsiniz. Model indirme işleminin durumunu kontrol edebilirsiniz. model yöneticisinin isModelDownloaded() yöntemini kullanarak görevi tamamlayın.

Çevirmeni çalıştırmadan önce bunu onaylamanız gerekse de hem uzaktan barındırılan hem de yerel olarak paketlenen model yorumlayıcıyı örneklendirirken şu kontrolü yapmanız mantıklıdır: yerel modelden ve yerel makine öğreniminden modelini kullanmanız gerekir.

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 modelle ilgili ayarını devre dışı bırakmanız gerekir. (örneğin, kullanıcı arayüzünüzün bir kısmını devre dışı bırakan veya gizleyen) modelin indirildiğini onaylayın. Bunu bir dinleyici ekleyerek model yöneticisinin download() yöntemine:

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

Ardından, model yorumlayıcının giriş ve çıkış biçimlerini yapılandırın.

TensorFlow Lite modeli girdi olarak alır ve bir veya daha fazla çıkış olarak üretir çok boyutlu diziler. Bu diziler byte, int, long veya float değerleri. Şunu yapmalısınız: ML Kit'ini, kullandığınız dizilerin sayısı ve boyutlarıyla ("şekli") en iyi uygulamalardan bahsedeceğiz.

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ışının biçimini belirledikten sonra uygulamanızın model çevirmenini yapılandırmak için bir FirebaseModelInputOutputOptions nesnesini tanımlayın.

Örneğin, kayan noktalı görüntü sınıflandırma modeli için NBir grubu temsil eden float değerlerinden oluşan x224x224x3 dizisi N 224x224 üç kanallı (RGB) resimler ve aşağıdakilerin bir listesi olarak üretilebilir: Her biri resmin üyesi olma olasılığını temsil eden 1.000 float değeri kategoriden birini seçmeniz gerekir.

Böyle bir model için model çevirmeninin giriş ve çıkışını yapılandırırsınız. aşağıdaki gibidir:

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ş verilerinde çıkarım yap

Son olarak, modeli kullanarak çıkarım yapmak için giriş verilerinizi alın ve doğru şekle sokmanız gerekir.

Örneğin, giriş şekli [1 224 224 3] kayan nokta değerlerini bulmak için Bitmap nesnesini ifade eder:

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, FirebaseModelInputs ve bu verileri ve modelin giriş ve çıkış özelliklerini model çevirmeni'nin run yöntemi:

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 getOutput() yöntemini çağırarak sonucu alabilirsiniz başarılı dinleyiciye iletilmesini sağlayan bir araçtır. Ö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]

Sonucu 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 sonuç dizinlerini, temsil ettikleri etiketlerle eşler:

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 kullanıcılara nasıl sunduğunuz fark etmeksizin ML Kit, ML Kit, bu dosyaları standart serileştirilmiş protobuf biçiminde depolar. yerel depolama.

Teoride bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Ancak, pratikte çoğu model, uygulamaya özgüdür ve her bir model rakiplerin parçalarının parçalarının sökülüp parçalarının parçalarının kodunuzu tekrarlamanız gerekir. Yine de, anahtar kelimeleri kullanmadan önce bu riskin farkında olmalısınız. bir model oluşturabilirsiniz.

Android API düzey 21 (Lollipop) ve daha yeni sürümlerde model dizini hariç tutulur.

Android API düzeyi 20 ve daha eski sürümlerde model bir dizine indirilir. Uygulama gizli modunda com.google.firebase.ml.custom.models olarak adlandırıldı dahili depolama. BackupAgent kullanarak dosya yedeklemeyi etkinleştirdiyseniz bu dizini hariç tutabilirsiniz.