Android'de özel bir TensorFlow Lite modeli kullanın

Uygulamanız özel TensorFlow Lite modelleri kullanıyorsa modellerinizi dağıtmak için Firebase ML'yi 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ı modelleri farklı kullanıcı gruplarına dinamik olarak sunabilirsiniz.

TensorFlow Lite modelleri

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

Sen başlamadan önce

  1. Henüz yapmadıysanız, Android projenize Firebase'i ekleyin .
  2. Firebase Android BoM kullanarak, modülünüzdeki (uygulama düzeyi) Gradle dosyanızdaki (genellikle app/build.gradle ) Firebase ML model indiricisi Android kitaplığının bağımlılığını bildirin.

    Ayrıca, Firebase ML model indiricisini kurmanın bir parçası olarak, uygulamanıza TensorFlow Lite SDK'yı eklemeniz gerekir.

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.1.0')
    
        // Declare 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 declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Firebase Android BoM'u kullanarak uygulamanız her zaman Firebase Android kitaplıklarının uyumlu sürümlerini kullanır.

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

    Firebase Malzeme Listesini kullanmamayı seçerseniz, her bir Firebase kitaplık sürümünü 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'yi kullanmanızı şiddetle tavsiye ettiğimizi unutmayın; bu, tüm sürümlerin uyumlu olmasını sağlar.

    dependencies {
        // Declare 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:24.0.3'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.1.0')
    
        // Declare 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-ktx'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }

    Firebase Android BoM'u kullanarak uygulamanız her zaman Firebase Android kitaplıklarının uyumlu sürümlerini kullanır.

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

    Firebase Malzeme Listesini kullanmamayı seçerseniz, her bir Firebase kitaplık sürümünü 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'yi kullanmanızı şiddetle tavsiye ettiğimizi unutmayın; bu, tüm sürümlerin uyumlu olmasını sağlar.

    dependencies {
        // Declare 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-ktx:24.0.3'
    // Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    }
  3. Uygulamanızın bildiriminde, İNTERNET izninin gerekli olduğunu beyan edin:
    <uses-permission android:name="android.permission.INTERNET" />

1. Modelinizi dağıtın

Firebase konsolunu veya Firebase Admin Python ve Node.js SDK'larını kullanarak özel TensorFlow modellerinizi dağıtın. Özel modelleri dağıtma ve yönetme konusuna bakın.

Firebase projenize özel bir model ekledikten sonra, belirttiğiniz adı kullanarak uygulamalarınızda modele başvurabilirsiniz. İstediğiniz zaman yeni bir TensorFlow Lite modelini dağıtabilir ve yeni modeli getModel() çağırarak kullanıcıların cihazlarına indirebilirsiniz (aşağıya bakın).

2. Modeli cihaza indirin ve bir TensorFlow Lite yorumlayıcısını başlatın

TensorFlow Lite modelinizi uygulamanızda kullanmak için öncelikle modelin en son sürümünü cihaza indirmek için Firebase ML SDK'yı kullanın. Ardından, modelle bir TensorFlow Lite yorumlayıcısının örneğini oluşturun.

Model indirmeyi başlatmak için, yüklediğinizde modele atadığınız adı, her zaman en son modeli indirmek isteyip istemediğinizi ve indirmeye izin vermek istediğiniz koşulları belirterek model indiricisinin getModel() yöntemini çağırın.

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

İndirme türü Tanım
LOCAL_MODEL Cihazdan yerel modeli alın. Kullanılabilir yerel model yoksa, bu LATEST_MODEL gibi davranır. Model güncellemelerini kontrol etmekle ilgilenmiyorsanı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 adlar altında yüklüyorsunuz (önerilir).
LOCAL_MODEL_UPDATE_IN_BACKGROUND Cihazdan yerel modeli alın ve arka planda modeli güncellemeye başlayın. Kullanılabilir yerel model yoksa, bu LATEST_MODEL gibi davranır.
SON MODEL En son modeli alın. Yerel model en son sürümse, yerel modeli döndürür. Aksi takdirde, en son modeli indirin. Bu davranış, en son sürüm indirilene kadar engellenir (önerilmez). Bu davranışı yalnızca en son sürüme açıkça ihtiyaç duyduğunuz durumlarda kullanın.

Modelin indirildiğini onaylayana kadar modelle ilgili işlevleri devre dışı bırakmalısınız (örneğin, kullanıcı arayüzünüzün gri renkte görünmesi veya bir kısmını gizleme).

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

Kotlin+KTX

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

Birçok uygulama indirme görevini başlatma kodunda başlatır, ancak bunu modeli kullanmaya ihtiyaç duymadan önce herhangi bir noktada yapabilirsiniz.

3. Girdi verileri üzerinde çıkarım gerçekleştirin

Modelinizin giriş ve çıkış şekillerini alın

TensorFlow Lite model yorumlayıcısı girdi olarak alır ve çıktı olarak bir veya daha fazla çok boyutlu dizi üretir. Bu diziler byte , int , long veya float değerler içerir. Bir modele veri aktarmadan veya 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:

piton

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 çıktı:

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

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

yorumlayıcıyı çalıştırın

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

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

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

Kotlin+KTX

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

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

Java

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

Kotlin+KTX

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

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

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

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

Kotlin+KTX

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

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 depolamada standart serileştirilmiş protobuf biçiminde saklar.

Teorik olarak bu, herkesin modelinizi kopyalayabileceği anlamına gelir. Bununla birlikte, pratikte, çoğu model uygulamaya o kadar özeldir ve optimizasyonlarla karıştırılmıştır ki, risk rakiplerinizin kodunuzu söküp yeniden kullanma riskine benzer. Yine de, 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 yedeklemeden hariç tutulan bir dizine indirilir.

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