Android-এ কাস্টম TensorFlow Lite মডেল ব্যবহার করা

আপনার অ্যাপ কাস্টম TensorFlow Lite মডেল ব্যবহার করলে, আপনার মডেল ডেপ্লয় করতে Firebase ML ব্যবহার করতে পারবেন। Firebase-এর মাধ্যমে মডেল ডেপ্লয় করার মাধ্যমে, আপনি নিজের অ্যাপের প্রাথমিক ডাউনলোড সাইজ কমাতে এবং আপনার অ্যাপের নতুন ভার্সন রিলিজ না করেই আপনার অ্যাপের ML মডেল আপডেট করতে পারবেন। এছাড়াও, Remote Config ও A/B Testing-এর সাহায্যে, আপনি ডাইনামিক উপায়ে ব্যবহারকারীদের বিভিন্ন সেটে আলাদা আলাদা মডেল পরিবেশন করতে পারবেন।

TensorFlow Lite মডেল

TensorFlow Lite মডেল হল ML মডেল যা মোবাইল ডিভাইসে রান করার জন্য অপ্টিমাইজ করা হয়েছে। TensorFlow Lite মডেল পেতে:

শুরু করার আগে

  1. আপনি আগে থেকে না করে থাকলে, আপনার Android প্রোজেক্টে Firebase যোগ করুন।
  2. আপনার মডিউল (অ্যাপ-লেভেল) Gradle ফাইলে (সাধারণত <project>/<app-module>/build.gradle.kts বা <project>/<app-module>/build.gradle), Android-এর জন্য Firebase ML মডেল ডাউনলোডার লাইব্রেরির জন্য ডিপেন্ডেন্সি যোগ করুন। লাইব্রেরি ভার্সনিং কন্ট্রোল করতে Firebase Android BoM ব্যবহার করার সাজেশন দিই।

    এছাড়াও, Firebase ML মডেল ডাউনলোডার সেট-আপ করার অংশ হিসেবে, আপনাকে অ্যাপে TensorFlow Lite SDK যোগ করতে হবে।

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:34.19.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 ব্যবহার করার মাধ্যমে, আপনার অ্যাপ সবসময় Firebase Android লাইব্রেরির মানানসই ভার্সন ব্যবহার করবে।

    (বিকল্প)  BoM ব্যবহার না করে Firebase লাইব্রেরি নির্ভরতা যোগ করুন

    আপনি Firebase BoM ব্যবহার না করার বিকল্প বেছে নিলে, আপনাকে অবশ্যই এর ডিপেন্ডেন্সি লাইনে প্রতিটি Firebase লাইব্রেরি ভার্সন উল্লেখ করতে হবে।

    মনে রাখবেন, আপনার অ্যাপে একাধিক Firebase লাইব্রেরি ব্যবহার করলে, লাইব্রেরি ভার্সন ম্যানেজ করার জন্য আমরা BoM ব্যবহার করার জন্য অত্যন্ত সাজেস্ট করি, এটি নিশ্চিত করে যে সব ভার্সনই মানানসই।

    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. আপনার অ্যাপের ম্যানিফেস্টে, ঘোষণা করুন যে INTERNET অনুমতি প্রয়োজন:
    <uses-permission android:name="android.permission.INTERNET" />

১. আপনার মডেল ডেপ্লয় করা

Firebase কনসোল বা Firebase Admin Python এবং Node.js SDK ব্যবহার করে আপনার কাস্টম TensorFlow মডেল ডিপ্লয় করুন। কাস্টম মডেল ডেপ্লয় ও ম্যানেজ করা দেখুন।

Firebase প্রোজেক্টে কাস্টম মডেল যোগ করার পরে, আপনি যে নাম নির্দিষ্ট করেছেন সেটি ব্যবহার করে অ্যাপে মডেলের রেফারেন্স দিতে পারবেন। আপনি যেকোনও সময়, নতুন TensorFlow Lite মডেল ডেপ্লয় করতে পারেন এবং getModel() কল করে (নিচে দেখুন) ব্যবহারকারীর ডিভাইসে নতুন মডেল ডাউনলোড করতে পারেন।

২. ডিভাইসে মডেল ডাউনলোড করুন এবং TensorFlow Lite ইন্টারপ্রেটার ইনিশিয়ালাইজ করুন

আপনার অ্যাপে TensorFlow Lite মডেল ব্যবহার করতে, প্রথমে Firebase ML SDK ব্যবহার করে ডিভাইসে মডেলের লেটেস্ট ভার্সন ডাউনলোড করুন। তারপর, মডেলের সাথে TensorFlow Lite ইন্টারপ্রেটার ইনস্ট্যানশিয়েট করুন।

মডেল ডাউনলোড শুরু করতে, মডেল ডাউনলোডার getModel() মেথডকে কল করুন, আপনি আপলোড করার সময় মডেলটিকে যে নাম অ্যাসাইন করেছিলেন সেটি উল্লেখ করুন, আপনি সর্বদা লেটেস্ট মডেল ডাউনলোড করতে চান কিনা এবং আপনি যে শর্তের অধীনে ডাউনলোড করার অনুমতি দিতে চান।

আপনি তিনটি ডাউনলোড আচরণ থেকে বেছে নিতে পারবেন:

ডাউনলোডের ধরন বিবরণ
LOCAL_MODEL ডিভাইস থেকে লোকাল মডেল পান। কোনও লোকাল মডেল উপলভ্য না থাকলে, এটি LATEST_MODEL-এর মতো আচরণ করে। মডেল আপডেট চেক করার ব্যাপারে আগ্রহী না হলে এই ডাউনলোড করার ধরন ব্যবহার করুন। যেমন, আপনি মডেলের নাম রিট্রিভ করতে রিমোট কনফিগারেশন ব্যবহার করছেন এবং আপনি সবসময় নতুন নামে মডেল আপলোড করেন (সাজেস্ট করা)।
LOCAL_MODEL_UPDATE_IN_BACKGROUND ডিভাইস থেকে লোকাল মডেল পান এবং ব্যাকগ্রাউন্ডে মডেল আপডেট করা শুরু করুন। কোনও লোকাল মডেল উপলভ্য না থাকলে, এটি LATEST_MODEL-এর মতো আচরণ করে।
LATEST_MODEL লেটেস্ট মডেল পান। লোকাল মডেলটি লেটেস্ট ভার্সন হলে, লোকাল মডেলটি রিটার্ন করে। অন্যথায়, লেটেস্ট মডেল ডাউনলোড করুন। লেটেস্ট ভার্সন ডাউনলোড না করা পর্যন্ত এই আচরণ ব্লক করা হবে (সাজেস্ট করা হয় না)। আপনি যদি স্পষ্টভাবে লেটেস্ট ভার্সন চান, শুধুমাত্র সেইসব ক্ষেত্রে এই আচরণ ব্যবহার করুন।

মডেল ডাউনলোড করা হয়েছে বলে নিশ্চিত না হওয়া পর্যন্ত, মডেল-সম্পর্কিত ফাংশনালিটি বন্ধ করে দিন—যেমন, আপনার UI-এর অংশ গ্রে-আউট বা লুকিয়ে দিন।

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

অনেক অ্যাপ তাদের ইনিশিয়ালাইজেশন কোডে ডাউনলোড টাস্ক শুরু করে, কিন্তু মডেল ব্যবহার করার প্রয়োজন হওয়ার আগে আপনি যেকোনও সময় এটি করতে পারেন।

৩. ইনপুট ডেটা থেকে ফলাফল অনুমান করা

আপনার মডেলের ইনপুট ও আউটপুট শেপ পাওয়া

TensorFlow Lite মডেল ইন্টারপ্রেটার ইনপুট হিসেবে নেয় এবং আউটপুট হিসেবে এক বা একাধিক মাল্টিডাইমেনশনাল অ্যারে তৈরি করে। এইসব অ্যারেতে byte, int, long অথবা float ভ্যালু থাকে। কোনও মডেলে ডেটা পাস করা বা তার ফলাফল ব্যবহার করার আগে, আপনাকে অবশ্যই মডেলের ব্যবহার করা অ্যারের সংখ্যা ও ডাইমেনশন ("শেপ") জানতে হবে।

আপনি নিজে মডেল তৈরি করে থাকলে অথবা মডেলের ইনপুট ও আউটপুট ফরম্যাট ডকুমেন্টেড থাকলে, আপনার কাছে হয়ত আগেই এই তথ্য আছে। আপনার মডেলের ইনপুট ও আউটপুটের আকার ও ডেটা টাইপ না জানলে, আপনার মডেল পরীক্ষা করে দেখতে TensorFlow Lite ইন্টারপ্রেটার ব্যবহার করতে পারবেন। যেমন:

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

আউটপুটের উদাহরণ:

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

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

ইন্টারপ্রেটার রান করানো

আপনার মডেলের ইনপুট ও আউটপুটের ফর্ম্যাট নির্ধারণ করার পরে, আপনার ইনপুট ডেটা পান এবং আপনার মডেলের জন্য সঠিক শেপের ইনপুট পেতে ডেটার উপর প্রয়োজনীয় যেকোনও ট্রান্সফর্মেশন প্রয়োগ করুন।

যেমন, আপনার কাছে যদি এমন কোনও ইমেজ ক্লাসিফিকেশন মডেল থাকে যার ইনপুট শেপ হল [1 224 224 3] ফ্লোটিং-পয়েন্ট ভ্যালু, তাহলে আপনি নিম্নলিখিত উদাহরণে দেখানো Bitmap অবজেক্ট থেকে একটি ইনপুট ByteBuffer জেনারেট করতে পারবেন:

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

তারপর, মডেলের আউটপুট কন্টেন করার জন্য যথেষ্ট ByteBuffer বড় মেমরি বরাদ্দ করুন এবং TensorFlow Lite ইন্টারপ্রেটারের run() মেথডে ইনপুট বাফার ও আউটপুট বাফার পাস করুন। যেমন, [1 1000] ফ্লোটিং-পয়েন্ট ভ্যালুর আউটপুট শেপের জন্য:

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

আপনি কীভাবে আউটপুট ব্যবহার করবেন তা নির্ভর করে আপনি কোন মডেল ব্যবহার করছেন তার উপর।

যেমন, আপনি যদি শ্রেণীবিভাগ করছেন, তাহলে পরবর্তী ধাপ হিসেবে, আপনি ফলাফলের ইন্ডেক্সকে সেই লেবেলের সাথে ম্যাপ করতে পারেন যেগুলি সেগুলিকে প্রতিনিধিত্ব করে:

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

পরিশিষ্ট: মডেলের নিরাপত্তা

আপনি যেভাবে TensorFlow Lite মডেল উপলভ্য করুন না কেন, Firebase ML, Firebase ML সেগুলি লোকাল স্টোরেজে স্ট্যান্ডার্ড সিরিয়ালাইজড প্রোটোবাফ ফর্ম্যাটে সেভ করে।

তত্ত্বগতভাবে, এর অর্থ হল যে কেউ আপনার মডেল কপি করতে পারবেন। তবে, বাস্তবে, বেশিরভাগ মডেলই এত বেশি অ্যাপ্লিকেশন-নির্দিষ্ট এবং অপ্টিমাইজেশনের মাধ্যমে অস্পষ্ট করা হয় যে ঝুঁকিটি আপনার কোড ডিসঅ্যাসেম্বল করা এবং পুনরায় ব্যবহার করার ক্ষেত্রে প্রতিযোগীদের ঝুঁকির মতোই। তবে, আপনার অ্যাপে কাস্টম মডেল ব্যবহার করার আগে এই ঝুঁকি সম্পর্কে সচেতন থাকা উচিত।

Android API লেভেল 21 (Lollipop) ও এর পরের যেকোনও ভার্সনে, মডেলটি এমন একটি ডিরেক্টরিতে ডাউনলোড করা হয় যা অটোমেটিক ব্যাক-আপ থেকে বাদ দেওয়া হয়।

Android API লেভেল ২০ ও এর আগের ভার্সনে, মডেলটি com.google.firebase.ml.custom.models নামের ডিরেক্টরিতে অ্যাপ-প্রাইভেট ইন্টার্নাল স্টোরেজে ডাউনলোড করা হয়। আপনি BackupAgent ব্যবহার করে ফাইল ব্যাক-আপ চালু করে থাকলে, এই ডিরেক্টরি বাদ দিতে পারেন।