Android'de özel TensorFlow Lite modeli kullanma

Uygulamanız özel TensorFlow Lite modelleri kullanıyorsa modellerinizi dağıtmak için Firebase ML hizmetini kullanabilirsiniz. Modelleri Firebase ile dağıtarak uygulamanızın ilk indirme boyutunu küçültebilir ve uygulamanızın yeni bir sürümünü yayınlamadan uygulamanızın ML modellerini güncelleyebilirsiniz. Ayrıca Remote Config ve A/B Testing ile farklı kullanıcı gruplarına dinamik olarak farklı modeller sunabilirsiniz.

TensorFlow Lite modelleri

TensorFlow Lite modelleri, mobil cihazlarda çalışacak şekilde optimize edilmiş ML modelleridir. TensorFlow Lite modeli edinmek için:

Başlamadan önce

  1. Henüz yapmadıysanız Firebase'i Android projenize ekleyin.
  2. Modülünüzün (uygulama düzeyinde) Gradle dosyasında (genellikle <project>/<app-module>/build.gradle.kts veya <project>/<app-module>/build.gradle) Android için Firebase ML model indirici kitaplığının bağımlılığını ekleyin. Kitaplık sürümünü kontrol etmek için Firebase Android BoM kullanmanızı öneririz.

    Ayrıca, Firebase ML model indiriciyi ayarlarken TensorFlow Lite SDK'sını uygulamanıza eklemeniz gerekir.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:35.1.0"))
    
        // Add the dependency for the Firebase ML model downloader library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-ml-modeldownloader")
    // Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0")
    }

    Firebase Android BoM kullanarak uygulamanızın her zaman Firebase Android kitaplıklarının uyumlu sürümlerini kullanmasını sağlayabilirsiniz.

    (Alternatif)  BoM kullanmadan Firebase kitaplığı bağımlılıklarını ekleme

    Firebase BoM kullanmamayı tercih ederseniz her Firebase kitaplığı sürümünü kendi bağımlılık satırında belirtmeniz gerekir.

    Uygulamanızda birden fazla Firebase kitaplığı kullanıyorsanız kitaplık sürümlerini yönetmek için BoM kullanmanızı önemle tavsiye ederiz. Bu sayede tüm sürümlerin uyumlu olmasını sağlayabilirsiniz.

    dependencies {
        // Add the dependency for the Firebase ML model downloader library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-ml-modeldownloader:26.1.1")
    // Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0")
    }
  3. Uygulamanızın manifest dosyasında INTERNET izninin gerekli olduğunu beyan edin:
    <uses-permission android:name="android.permission.INTERNET" />

1. Modelinizi dağıtma

Özel TensorFlow modellerinizi Firebase konsolunu veya Firebase Admin Python ve Node.js SDK'larını kullanarak dağıtın. Özel modelleri dağıtma ve yönetme başlıklı makaleyi inceleyin.

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 dağıtabilir ve getModel() yöntemini çağırarak yeni modeli kullanıcıların cihazlarına indirebilirsiniz (aşağıya bakın).

2. Modeli cihaza indirme ve TensorFlow Lite yorumlayıcısını başlatma

TensorFlow Lite modelinizi uygulamanızda kullanmak için önce Firebase ML SDK'sını kullanarak modelin en yeni sürümünü cihaza indirin. Ardından, modelle birlikte bir TensorFlow Lite yorumlayıcısı örneği oluşturun.

Model indirme işlemini başlatmak için model indiricinin getModel() yöntemini çağırın. Bu yöntemde, modeli yüklerken atadığınız adı, her zaman en son modeli indirmek isteyip istemediğinizi ve indirme işlemine izin vermek istediğiniz koşulları belirtin.

Üç indirme davranışından birini seçebilirsiniz:

İndirme türü Açıklama
LOCAL_MODEL Cihazdan yerel modeli alın. Yerel model yoksa bu, LATEST_MODEL gibi davranır. Model güncellemelerini kontrol etmek istemiyorsanız bu indirme türünü kullanın. Örneğin, model adlarını almak için Remote Config'i kullanıyorsunuz ve modelleri her zaman yeni adlarla yüklüyorsunuz (önerilir).
LOCAL_MODEL_UPDATE_IN_BACKGROUND Cihazdan yerel modeli alın ve arka planda modeli güncellemeye başlayın. Yerel model yoksa bu, LATEST_MODEL gibi davranır.
LATEST_MODEL En yeni modeli edinin. Yerel model en yeni sürümse yerel modeli döndürür. Aksi takdirde en son modeli indirin. Bu davranış, en yeni sürüm indirilene kadar engellenir (önerilmez). Bu davranışı yalnızca en yeni sürüme açıkça ihtiyaç duyduğunuz durumlarda kullanın.

Modelin indirildiğini onaylayana kadar modelle ilgili işlevleri devre dışı bırakmanız (ör. kullanıcı arayüzünüzün bir kısmını devre dışı bırakmanız veya gizlemeniz) gerekir.

Kotlin

val conditions = CustomModelDownloadConditions.Builder()
        .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
        .build()
FirebaseModelDownloader.getInstance()
        .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND,
            conditions)
        .addOnSuccessListener { model: CustomModel? ->
            // Download complete. Depending on your app, you could enable the ML
            // feature, or switch from the local model to the remote model, etc.

            // The CustomModel object contains the local path of the model file,
            // which you can use to instantiate a TensorFlow Lite interpreter.
            val modelFile = model?.file
            if (modelFile != null) {
                interpreter = Interpreter(modelFile)
            }
        }

Java

CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder()
    .requireWifi()  // Also possible: .requireCharging() and .requireDeviceIdle()
    .build();
FirebaseModelDownloader.getInstance()
    .getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
    .addOnSuccessListener(new OnSuccessListener<CustomModel>() {
      @Override
      public void onSuccess(CustomModel model) {
        // Download complete. Depending on your app, you could enable the ML
        // feature, or switch from the local model to the remote model, etc.

        // The CustomModel object contains the local path of the model file,
        // which you can use to instantiate a TensorFlow Lite interpreter.
        File modelFile = model.getFile();
        if (modelFile != null) {
            interpreter = new Interpreter(modelFile);
        }
      }
    });

Birçok uygulama, indirme görevini başlatma kodunda başlatır ancak modeli kullanmanız gerekmeden önce herhangi bir noktada da başlatabilirsiniz.

3. Giriş verileri üzerinde çıkarım yapma

Modelinizin giriş ve çıkış şekillerini alma

TensorFlow Lite model yorumlayıcısı, giriş olarak bir veya daha fazla çok boyutlu dizi alır ve çıkış olarak bir veya daha fazla çok boyutlu dizi üretir. Bu diziler byte, int, long veya float değerlerini içerir. Bir modele veri aktarmadan veya modelin sonucunu kullanmadan önce modelinizin kullandığı dizilerin sayısını ve boyutlarını ("şekil") bilmeniz gerekir.

Modeli kendiniz oluşturduysanız veya modelin giriş ve çıkış biçimi belgelenmişse bu bilgilere zaten sahip olabilirsiniz. Modelinizin giriş ve çıkışının şeklini ve veri türünü bilmiyorsanız modelinizi incelemek için TensorFlow Lite yorumlayıcısını kullanabilirsiniz. Örneğin:

Python

import tensorflow as tf

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

# Print input shape and type
inputs = interpreter.get_input_details()
print('{} input(s):'.format(len(inputs)))
for i in range(0, len(inputs)):
    print('{} {}'.format(inputs[i]['shape'], inputs[i]['dtype']))

# Print output shape and type
outputs = interpreter.get_output_details()
print('\n{} output(s):'.format(len(outputs)))
for i in range(0, len(outputs)):
    print('{} {}'.format(outputs[i]['shape'], outputs[i]['dtype']))

Örnek çıkış:

1 input(s):
[  1 224 224   3] <class 'numpy.float32'>

1 output(s):
[1 1000] <class 'numpy.float32'>

Yorumlayıcıyı çalıştırma

Modelinizin giriş ve çıkış biçimini belirledikten sonra giriş verilerinizi alın ve modeliniz için doğru biçimde giriş elde etmek üzere veriler üzerinde gerekli dönüşümleri gerçekleştirin.

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

Kotlin

val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
for (y in 0 until 224) {
    for (x in 0 until 224) {
        val px = bitmap.getPixel(x, y)

        // Get channel values from the pixel value.
        val r = Color.red(px)
        val g = Color.green(px)
        val b = Color.blue(px)

        // Normalize channel values to [-1.0, 1.0]. This requirement depends on the model.
        // For example, some models might require values to be normalized to the range
        // [0.0, 1.0] instead.
        val rf = (r - 127) / 255f
        val gf = (g - 127) / 255f
        val bf = (b - 127) / 255f

        input.putFloat(rf)
        input.putFloat(gf)
        input.putFloat(bf)
    }
}

Java

Bitmap bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true);
ByteBuffer input = ByteBuffer.allocateDirect(224 * 224 * 3 * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < 224; y++) {
    for (int x = 0; x < 224; x++) {
        int px = bitmap.getPixel(x, y);

        // Get channel values from the pixel value.
        int r = Color.red(px);
        int g = Color.green(px);
        int b = Color.blue(px);

        // Normalize channel values to [-1.0, 1.0]. This requirement depends
        // on the model. For example, some models might require values to be
        // normalized to the range [0.0, 1.0] instead.
        float rf = (r - 127) / 255.0f;
        float gf = (g - 127) / 255.0f;
        float bf = (b - 127) / 255.0f;

        input.putFloat(rf);
        input.putFloat(gf);
        input.putFloat(bf);
    }
}

Ardından, modelin çıkışını içerecek kadar büyük bir ByteBuffer ayırın ve giriş arabelleği ile çıkış arabelleğini TensorFlow Lite yorumlayıcısının run() yöntemine iletin. Örneğin, [1 1000] kayan nokta değerinden oluşan bir çıkış şekli için:

Kotlin

val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
interpreter?.run(input, modelOutput)

Java

int bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder());
interpreter.run(input, modelOutput);

Çıkışı 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ımda sonucun dizinlerini temsil ettikleri etiketlerle eşleyebilirsiniz:

Kotlin

modelOutput.rewind()
val probabilities = modelOutput.asFloatBuffer()
try {
    val reader = BufferedReader(
            InputStreamReader(assets.open("custom_labels.txt")))
    for (i in probabilities.capacity()) {
        val label: String = reader.readLine()
        val probability = probabilities.get(i)
        println("$label: $probability")
    }
} catch (e: IOException) {
    // File not found?
}

Java

modelOutput.rewind();
FloatBuffer probabilities = modelOutput.asFloatBuffer();
try {
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(getAssets().open("custom_labels.txt")));
    for (int i = 0; i < probabilities.capacity(); i++) {
        String label = reader.readLine();
        float probability = probabilities.get(i);
        Log.i(TAG, String.format("%s: %1.4f", label, probability));
    }
} catch (IOException e) {
    // File not found?
}

Ek: Model güvenliği

TensorFlow Lite modellerinizi Firebase ML için nasıl kullanılabilir hale getirdiğinizden bağımsız olarak Firebase ML, bunları yerel depolama alanında standart serileştirilmiş protobuf biçiminde depolar.

Teorik olarak bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Ancak pratikte çoğu model uygulamaya özeldir ve optimizasyonlar nedeniyle gizlenir. Bu nedenle, risk rakiplerinizin kodunuzu parçalara ayırıp yeniden kullanmasıyla benzerdir. Yine de uygulamanızda özel bir model kullanmadan önce bu riskin farkında olmanız gerekir.

Android API düzeyi 21 (Lollipop) ve sonraki sürümlerde model, otomatik yedeklemenin dışında tutulan bir dizine indirilir.

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