Android पर मशीन लर्निंग किट की मदद से, TensorFlow Lite मॉडल का इस्तेमाल करके अनुमान लगाना

उपयोगकर्ता के डिवाइस पर, TensorFlow Lite मॉडल की मदद से अनुमान लगाने के लिए, ML Kit का इस्तेमाल किया जा सकता है.

इस एपीआई का इस्तेमाल करने के लिए, Android SDK के लेवल 16 (जैली बीन) या उसके बाद के वर्शन की ज़रूरत होती है.

वेब कंटेनर इंस्टॉल करने से पहले

  1. अगर आपने पहले से Firebase को नहीं जोड़ा है, तो अपने Android प्रोजेक्ट में Firebase जोड़ें.
  2. अपने मॉड्यूल (ऐप्लिकेशन-लेवल) की Gradle फ़ाइल (आम तौर पर app/build.gradle) में ML Kit Android लाइब्रेरी के लिए डिपेंडेंसी जोड़ें:
    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 Optimize Converter देखें.

अपने मॉडल को होस्ट या बंडल करें

ऐप्लिकेशन में अनुमान लगाने के लिए, TensorFlow Lite मॉडल का इस्तेमाल करने से पहले, आपको ML Kit में वह मॉडल उपलब्ध कराना होगा. ML किट में TensorFlow Lite मॉडल का इस्तेमाल किया जा सकता है. ये मॉडल Firebase का इस्तेमाल करके, रिमोट तरीके से होस्ट किए जाते हैं और इन्हें ऐप्लिकेशन बाइनरी के साथ बंडल किया जाता है या फिर दोनों का इस्तेमाल किया जा सकता है.

Firebase पर मॉडल होस्ट करके, ऐप्लिकेशन का नया वर्शन रिलीज़ किए बिना मॉडल को अपडेट किया जा सकता है. साथ ही, रिमोट कॉन्फ़िगरेशन और A/B टेस्टिंग का इस्तेमाल करके, उपयोगकर्ताओं के अलग-अलग सेट के लिए डाइनैमिक तरीके से अलग-अलग मॉडल दिखाए जा सकते हैं.

अगर मॉडल को सिर्फ़ Firebase के साथ होस्ट करके उपलब्ध कराना है, उसे अपने ऐप्लिकेशन के साथ बंडल नहीं करना है, तो अपने ऐप्लिकेशन के डाउनलोड साइज़ को कम किया जा सकता है. हालांकि, ध्यान रखें कि अगर इस मॉडल को आपके ऐप्लिकेशन के साथ बंडल नहीं किया गया है, तो मॉडल से जुड़ी कोई भी सुविधा तब तक उपलब्ध नहीं होगी, जब तक कि आपका ऐप्लिकेशन, मॉडल को पहली बार डाउनलोड नहीं करता.

मॉडल को अपने ऐप्लिकेशन के साथ बंडल करके, यह पक्का किया जा सकता है कि Firebase से होस्ट किया गया मॉडल उपलब्ध न होने पर भी, आपके ऐप्लिकेशन की एमएल सुविधाएं काम करती हों.

Firebase पर मॉडल होस्ट करें

Firebase पर अपना TensorFlow Lite मॉडल होस्ट करने के लिए:

  1. Firebase कंसोल के एमएल किट सेक्शन में, कस्टम टैब पर क्लिक करें.
  2. कस्टम मॉडल जोड़ें पर क्लिक करें (या कोई दूसरा मॉडल जोड़ें) पर क्लिक करें.
  3. एक ऐसा नाम दें जिसका इस्तेमाल, आपके Firebase प्रोजेक्ट में आपके मॉडल की पहचान करने के लिए किया जाएगा. इसके बाद, TensorFlow Lite मॉडल फ़ाइल (आम तौर पर, जिसके आखिर में .tflite या .lite होता है) अपलोड करें.
  4. अपने ऐप्लिकेशन के मेनिफ़ेस्ट में, यह बताएं कि इंटरनेट की अनुमति ज़रूरी है:
    <uses-permission android:name="android.permission.INTERNET" />
    

अपने Firebase प्रोजेक्ट में कोई कस्टम मॉडल जोड़ने के बाद, अपने ऐप्लिकेशन में उस मॉडल का रेफ़रंस देने के लिए, अपना बताया गया नाम इस्तेमाल करें. आपके पास किसी भी समय TensorFlow Lite का नया मॉडल अपलोड करने का विकल्प होता है. इसके बाद, आपका ऐप्लिकेशन नया मॉडल डाउनलोड करेगा और ऐप्लिकेशन के अगली बार रीस्टार्ट होने पर उसका इस्तेमाल करना शुरू कर देगा. आपके पास, डिवाइस से जुड़ी ज़रूरी शर्तें तय करने का विकल्प होता है. ये शर्तें, ऐप्लिकेशन को मॉडल अपडेट करने की कोशिश करने के लिए ज़रूरी होती हैं. इसकी जानकारी नीचे दी गई है.

ऐप्लिकेशन के साथ बंडल मॉडल

अपने TensorFlow Lite मॉडल को अपने ऐप्लिकेशन के साथ बंडल करने के लिए, मॉडल फ़ाइल (आम तौर पर .tflite या .lite पर खत्म होती है) को अपने ऐप्लिकेशन के assets/ फ़ोल्डर में कॉपी करें. (ऐसा हो सकता है कि पहले आपको app/ फ़ोल्डर पर राइट क्लिक करने के बाद, नया > फ़ोल्डर > ऐसेट फ़ोल्डर पर क्लिक करके फ़ोल्डर बनाना पड़े.

इसके बाद, अपने ऐप्लिकेशन की build.gradle फ़ाइल में इन्हें जोड़ें, ताकि यह पक्का किया जा सके कि ऐप्लिकेशन बनाते समय Gradle, मॉडल कंप्रेस न करे:

android {

    // ...

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

मॉडल फ़ाइल, ऐप्लिकेशन के पैकेज में शामिल की जाएगी और एमएल किट के लिए रॉ ऐसेट के तौर पर उपलब्ध होगी.

मॉडल लोड करें

अपने ऐप्लिकेशन में TensorFlow Lite मॉडल का इस्तेमाल करने के लिए, सबसे पहले ML किट को उन जगहों के साथ कॉन्फ़िगर करें जहां आपका मॉडल उपलब्ध है: जैसे कि Firebase का इस्तेमाल करके, रिमोट तरीके से, लोकल स्टोरेज में या दोनों का. अगर लोकल और रिमोट मॉडल, दोनों तय किए जाते हैं, तो उपलब्ध होने पर रिमोट मॉडल का इस्तेमाल किया जा सकता है. साथ ही, रिमोट मॉडल उपलब्ध न होने पर, लोकल तौर पर सेव किए गए मॉडल पर वापस जाया जा सकता है.

Firebase के होस्ट किए गए मॉडल को कॉन्फ़िगर करना

अगर आपने अपने मॉडल को Firebase के साथ होस्ट किया है, तो FirebaseCustomRemoteModel ऑब्जेक्ट बनाएं. साथ ही, उस नाम के बारे में बताएं जिसे आपने मॉडल को अपलोड करते समय असाइन किया था:

Java

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

Kotlin+KTX

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

इसके बाद, उन शर्तों को तय करते हुए मॉडल डाउनलोड टास्क शुरू करें जिनमें आपको डाउनलोड करने की अनुमति देनी है. अगर मॉडल, डिवाइस पर मौजूद नहीं है या मॉडल का नया वर्शन उपलब्ध है, तो टास्क, Firebase से मॉडल को एसिंक्रोनस रूप से डाउनलोड करेगा:

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+KTX

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+KTX

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+KTX

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+KTX

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

अगर आपके पास सिर्फ़ रिमोट तौर पर होस्ट किया गया मॉडल है, तो आपको मॉडल से जुड़ी फ़ंक्शनलिटी बंद करनी चाहिए. उदाहरण के लिए, अपने यूज़र इंटरफ़ेस (यूआई) के किसी हिस्से को धूसर करना या छिपाना. ऐसा तब तक करना चाहिए, जब तक आप मॉडल के डाउनलोड होने की पुष्टि न कर लें. इसके लिए, मॉडल मैनेजर के 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+KTX

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 Python इंटरप्रेटर का इस्तेमाल करें. जैसे:

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 वैल्यू का Nx224x224x3 अरे इनपुट के तौर पर, N 224x224 तीन चैनल (आरजीबी) इमेज के बैच को दिखाता है. इसके बाद, आउटपुट के तौर पर 1,000 float वैल्यू की सूची देता है. हर वैल्यू इस बात की संभावना दिखाती है कि इमेज, मॉडल की ओर से अनुमान लगाई गई 1,000 कैटगरी में से किसी एक कैटगरी का सदस्य हो.

ऐसे मॉडल के लिए, आपको मॉडल इंटरप्रेटर के इनपुट और आउटपुट को कॉन्फ़िगर करना होगा, जैसा कि नीचे दिखाया गया है:

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+KTX

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+KTX

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+KTX

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+KTX

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+KTX

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 उन्हें लोकल स्टोरेज में स्टैंडर्ड सीरियल वाले प्रोटोबफ़ फ़ॉर्मैट में सेव करता है.

सिद्धांत के तौर पर, इसका मतलब है कि कोई भी व्यक्ति आपके मॉडल की कॉपी बना सकता है. हालांकि, ज़्यादातर मॉडल, ऐप्लिकेशन के हिसाब से काम के होते हैं और ऑप्टिमाइज़ेशन की वजह से उलझाने वाले होते हैं. इस वजह से, आपके कोड को खोलने और उसका फिर से इस्तेमाल करने वाले प्रतिस्पर्धियों के मुकाबले जोखिम भरा होता है. फिर भी, अपने ऐप्लिकेशन में कस्टम मॉडल का इस्तेमाल करने से पहले आपको इस जोखिम के बारे में पता होना चाहिए.

Android के एपीआई लेवल 21 (Lollipop) और इसके बाद के वर्शन पर, मॉडल को ऐसी डायरेक्ट्री में डाउनलोड किया जाता है जिसके लिए अपने-आप बैकअप लेने की सुविधा उपलब्ध नहीं है.

Android के एपीआई लेवल 20 और इससे पहले के वर्शन पर, इस मॉडल को ऐप्लिकेशन के निजी स्टोरेज में com.google.firebase.ml.custom.models नाम की डायरेक्ट्री में डाउनलोड किया जाता है. अगर आपने BackupAgent का इस्तेमाल करके फ़ाइल का बैकअप लेने की सुविधा चालू की है, तो इस डायरेक्ट्री को बाहर रखें.