Android-এ ML Kit-এর সাহায্যে অনুমানের জন্য একটি TensorFlow Lite মডেল ব্যবহার করুন

আপনি এমএল কিট ব্যবহার করে একটি টেনসরফ্লো লাইট মডেলের সাহায্যে ডিভাইসেই ইনফারেন্স সম্পাদন করতে পারেন।

এই API-টির জন্য Android SDK লেভেল 16 (Jelly Bean) বা তার পরবর্তী সংস্করণ প্রয়োজন।

শুরু করার আগে

  1. যদি আগে থেকে না করে থাকেন, তাহলে আপনার অ্যান্ড্রয়েড প্রজেক্টে ফায়ারবেস যোগ করুন
  2. আপনার মডিউল (অ্যাপ-লেভেল) গ্রেডল ফাইলে (সাধারণত 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. আপনি যে TensorFlow মডেলটি ব্যবহার করতে চান, সেটিকে TensorFlow Lite ফরম্যাটে রূপান্তর করুন। দেখুন TOCO: TensorFlow Lite Optimizing Converter

আপনার মডেলটি হোস্ট বা বান্ডল করুন

আপনার অ্যাপে ইনফারেন্সের জন্য একটি TensorFlow Lite মডেল ব্যবহার করার আগে, আপনাকে অবশ্যই মডেলটি ML Kit-এর জন্য উপলব্ধ করতে হবে। ML Kit, Firebase ব্যবহার করে দূরবর্তীভাবে হোস্ট করা, অ্যাপ বাইনারির সাথে বান্ডেল করা, অথবা উভয় প্রকারের TensorFlow Lite মডেল ব্যবহার করতে পারে।

Firebase-এ একটি মডেল হোস্ট করার মাধ্যমে, আপনি অ্যাপের নতুন সংস্করণ প্রকাশ না করেই মডেলটি আপডেট করতে পারেন এবং Remote ConfigA/B Testing ব্যবহার করে বিভিন্ন ব্যবহারকারী গোষ্ঠীর কাছে গতিশীলভাবে ভিন্ন ভিন্ন মডেল পরিবেশন করতে পারেন।

আপনি যদি মডেলটিকে আপনার অ্যাপের সাথে বান্ডল না করে শুধু ফায়ারবেসে হোস্ট করার সিদ্ধান্ত নেন, তাহলে আপনি আপনার অ্যাপের প্রাথমিক ডাউনলোডের আকার কমাতে পারবেন। তবে মনে রাখবেন, যদি মডেলটি আপনার অ্যাপের সাথে বান্ডল করা না থাকে, তাহলে আপনার অ্যাপ প্রথমবার মডেলটি ডাউনলোড না করা পর্যন্ত মডেল-সম্পর্কিত কোনো কার্যকারিতাই উপলব্ধ হবে না।

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

ফায়ারবেসে মডেল হোস্ট করুন

আপনার TensorFlow Lite মডেলটি Firebase-এ হোস্ট করতে:

  1. Firebase কনসোলের ML Kit সেকশনে, Custom ট্যাবে ক্লিক করুন।
  2. কাস্টম মডেল যোগ করুন (অথবা অন্য মডেল যোগ করুন )-এ ক্লিক করুন।
  3. আপনার Firebase প্রোজেক্টে মডেলটিকে শনাক্ত করার জন্য একটি নাম নির্দিষ্ট করুন, তারপর TensorFlow Lite মডেল ফাইলটি আপলোড করুন (সাধারণত যার শেষে .tflite বা .lite থাকে)।
  4. আপনার অ্যাপের ম্যানিফেস্টে ঘোষণা করুন যে ইন্টারনেট পারমিশন প্রয়োজন:
    <uses-permission android:name="android.permission.INTERNET" />

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

একটি অ্যাপের মাধ্যমে মডেলগুলো একত্রিত করুন

আপনার অ্যাপের সাথে TensorFlow Lite মডেলটি বান্ডল করতে, মডেল ফাইলটি (সাধারণত .tflite বা .lite এক্সটেনশনযুক্ত) আপনার অ্যাপের assets/ ফোল্ডারে কপি করুন। (এর জন্য আপনাকে প্রথমে app/ ফোল্ডারে রাইট-ক্লিক করে, তারপর New > Folder > Assets Folder-এ ক্লিক করে ফোল্ডারটি তৈরি করে নিতে হতে পারে।)

এরপর, অ্যাপটি বিল্ড করার সময় Gradle যাতে মডেলগুলোকে কম্প্রেস না করে, তা নিশ্চিত করতে আপনার অ্যাপের build.gradle ফাইলে নিম্নলিখিতটি যোগ করুন:

android {

    // ...

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

মডেল ফাইলটি অ্যাপ প্যাকেজে অন্তর্ভুক্ত করা হবে এবং এমএল কিট-এর জন্য একটি র অ্যাসেট হিসেবে উপলব্ধ থাকবে।

মডেলটি লোড করুন

আপনার অ্যাপে TensorFlow Lite মডেল ব্যবহার করার জন্য, প্রথমে ML Kit-কে সেই অবস্থানগুলো দিয়ে কনফিগার করুন যেখানে আপনার মডেলটি রয়েছে: Firebase ব্যবহার করে রিমোটলি, লোকাল স্টোরেজে, অথবা উভয় স্থানে। যদি আপনি একটি লোকাল এবং একটি রিমোট মডেল উভয়ই নির্দিষ্ট করেন, তাহলে রিমোট মডেলটি উপলব্ধ থাকলে আপনি সেটি ব্যবহার করতে পারবেন, এবং রিমোট মডেলটি উপলব্ধ না থাকলে লোকালি-সংরক্ষিত মডেলটিতে ফিরে যেতে পারবেন।

একটি ফায়ারবেস-হোস্টেড মডেল কনফিগার করুন

আপনি যদি Firebase-এ আপনার মডেলটি হোস্ট করে থাকেন, তাহলে একটি FirebaseCustomRemoteModel অবজেক্ট তৈরি করুন এবং মডেলটি আপলোড করার সময় আপনি যে নামটি দিয়েছিলেন তা উল্লেখ করুন:

Java

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

Kotlin

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

এরপর, মডেল ডাউনলোড টাস্কটি শুরু করুন এবং কোন শর্তে আপনি ডাউনলোডের অনুমতি দিতে চান তা উল্লেখ করুন। যদি মডেলটি ডিভাইসে না থাকে, অথবা মডেলটির কোনো নতুন সংস্করণ উপলব্ধ থাকে, তাহলে টাস্কটি অ্যাসিঙ্ক্রোনাসভাবে ফায়ারবেস থেকে মডেলটি ডাউনলোড করবে:

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

val conditions = FirebaseModelDownloadConditions.Builder()
    .requireWifi()
    .build()
FirebaseModelManager.getInstance().download(remoteModel, conditions)
    .addOnCompleteListener {
        // Success.
    }

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

একটি স্থানীয় মডেল কনফিগার করুন

যদি আপনি আপনার অ্যাপের সাথে মডেলটি বান্ডল করে থাকেন, তাহলে TensorFlow Lite মডেলটির ফাইলের নাম উল্লেখ করে একটি FirebaseCustomLocalModel অবজেক্ট তৈরি করুন:

Java

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

Kotlin

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

আপনার মডেল থেকে একজন ইন্টারপ্রেটার তৈরি করুন

আপনার মডেল সোর্সগুলো কনফিগার করার পর, সেগুলোর যেকোনো একটি থেকে একটি FirebaseModelInterpreter অবজেক্ট তৈরি করুন।

আপনার কাছে যদি শুধুমাত্র একটি লোকালি-বান্ডেলড মডেল থাকে, তাহলে আপনার FirebaseCustomLocalModel অবজেক্ট থেকে একটি ইন্টারপ্রেটার তৈরি করুন:

Java

FirebaseModelInterpreter interpreter;
try {
    FirebaseModelInterpreterOptions options =
            new FirebaseModelInterpreterOptions.Builder(localModel).build();
    interpreter = FirebaseModelInterpreter.getInstance(options);
} catch (FirebaseMLException e) {
    // ...
}

Kotlin

val options = FirebaseModelInterpreterOptions.Builder(localModel).build()
val interpreter = FirebaseModelInterpreter.getInstance(options)

আপনার যদি দূরবর্তী স্থানে হোস্ট করা কোনো মডেল থাকে, তবে সেটি চালানোর আগে আপনাকে যাচাই করে নিতে হবে যে সেটি ডাউনলোড হয়েছে কি না। আপনি মডেল ম্যানেজারের isModelDownloaded() মেথড ব্যবহার করে মডেল ডাউনলোড টাস্কের অবস্থা পরীক্ষা করতে পারেন।

যদিও ইন্টারপ্রেটার চালানোর আগে আপনাকে কেবল এটি নিশ্চিত করতে হয়, আপনার কাছে যদি একটি রিমোটলি-হোস্টেড মডেল এবং একটি লোকালি-বান্ডেলড মডেল উভয়ই থাকে, তবে মডেল ইন্টারপ্রেটার ইনস্ট্যানশিয়েট করার সময় এই চেকটি করে নেওয়া যুক্তিযুক্ত হতে পারে: যদি রিমোট মডেলটি ডাউনলোড করা হয়ে থাকে তবে সেখান থেকে একটি ইন্টারপ্রেটার তৈরি করুন, এবং অন্যথায় লোকাল মডেল থেকে তৈরি করুন।

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

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
    .addOnSuccessListener { isDownloaded -> 
    val options =
        if (isDownloaded) {
            FirebaseModelInterpreterOptions.Builder(remoteModel).build()
        } else {
            FirebaseModelInterpreterOptions.Builder(localModel).build()
        }
    val interpreter = FirebaseModelInterpreter.getInstance(options)
}

আপনার কাছে যদি শুধুমাত্র একটি রিমোটলি-হোস্টেড মডেল থাকে, তাহলে মডেলটি ডাউনলোড হয়েছে কিনা তা নিশ্চিত না হওয়া পর্যন্ত আপনার মডেল-সম্পর্কিত কার্যকারিতা নিষ্ক্রিয় করে রাখা উচিত—উদাহরণস্বরূপ, আপনার UI-এর কোনো অংশ ধূসর করে দেওয়া বা লুকিয়ে রাখা। আপনি মডেল ম্যানেজারের download() মেথডে একটি লিসেনার সংযুক্ত করে এটি করতে পারেন:

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

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

মডেলের ইনপুট এবং আউটপুট নির্দিষ্ট করুন।

এরপর, মডেল ইন্টারপ্রেটারের ইনপুট এবং আউটপুট ফরম্যাটগুলো কনফিগার করুন।

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

আপনার মডেলের ইনপুট এবং আউটপুটের আকার ও ডেটা টাইপ যদি আপনার জানা না থাকে, তাহলে আপনি আপনার মডেলটি পরীক্ষা করার জন্য TensorFlow Lite পাইথন ইন্টারপ্রেটার ব্যবহার করতে পারেন। উদাহরণস্বরূপ:

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

আপনার মডেলের ইনপুট এবং আউটপুটের ফরম্যাট নির্ধারণ করার পরে, আপনি একটি FirebaseModelInputOutputOptions অবজেক্ট তৈরি করে আপনার অ্যাপের মডেল ইন্টারপ্রেটার কনফিগার করতে পারেন।

উদাহরণস্বরূপ, একটি ফ্লোটিং-পয়েন্ট ইমেজ ক্লাসিফিকেশন মডেল ইনপুট হিসেবে float মানের একটি N x 224 x 224 x 3 অ্যারে নিতে পারে, যা N 224 x 224 তিন-চ্যানেল (RGB) ছবির একটি ব্যাচকে প্রতিনিধিত্ব করে, এবং আউটপুট হিসেবে 1000টি float মানের একটি তালিকা তৈরি করতে পারে, যার প্রতিটি মান মডেলের পূর্বাভাস দেওয়া 1000টি বিভাগের মধ্যে কোনো একটির সদস্য হওয়ার সম্ভাবনাকে প্রতিনিধিত্ব করে।

এই ধরনের মডেলের জন্য, আপনি মডেল ইন্টারপ্রেটারের ইনপুট এবং আউটপুট নিচে দেখানো অনুযায়ী কনফিগার করবেন:

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

val inputOutputOptions = FirebaseModelInputOutputOptions.Builder()
        .setInputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 224, 224, 3))
        .setOutputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 5))
        .build()

ইনপুট ডেটার উপর অনুমান সম্পাদন করুন

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

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

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

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

এরপর, আপনার ইনপুট ডেটা দিয়ে একটি FirebaseModelInputs অবজেক্ট তৈরি করুন এবং সেটিকে ও মডেলের ইনপুট এবং আউটপুট স্পেসিফিকেশনকে মডেল ইন্টারপ্রেটারের run মেথডে পাস করুন:

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

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

কলটি সফল হলে, সাকসেস লিসেনারে পাঠানো অবজেক্টটির getOutput() মেথড কল করে আপনি আউটপুটটি পেতে পারেন। উদাহরণস্বরূপ:

Java

float[][] output = result.getOutput(0);
float[] probabilities = output[0];

Kotlin

val output = result.getOutput<Array<FloatArray>>(0)
val probabilities = output[0]

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

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

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

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

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

আপনি আপনার TensorFlow Lite মডেলগুলোকে ML Kit-এর কাছে যেভাবেই উপলব্ধ করুন না কেন, ML Kit সেগুলোকে লোকাল স্টোরেজে স্ট্যান্ডার্ড সিরিয়ালাইজড প্রোটোবাফ ফরম্যাটে সংরক্ষণ করে।

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

অ্যান্ড্রয়েড এপিআই লেভেল ২১ (ললিপপ) এবং এর পরবর্তী সংস্করণগুলোতে, মডেলটি এমন একটি ডিরেক্টরিতে ডাউনলোড করা হয় যা স্বয়ংক্রিয় ব্যাকআপের আওতার বাইরে থাকে

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