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: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 ব্যবহার করে, আপনার অ্যাপ সবসময় 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?
}

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

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

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

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

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