टेन्सरफ्लो लाइट एनएनएपीआई प्रतिनिधि

एंड्रॉइड न्यूरल नेटवर्क्स एपीआई (एनएनपीआई) एंड्रॉइड 8.1 (एपीआई स्तर 27) या उच्चतर चलाने वाले सभी एंड्रॉइड डिवाइसों पर उपलब्ध है। यह समर्थित हार्डवेयर त्वरक के साथ Android उपकरणों पर TensorFlow Lite मॉडल के लिए त्वरण प्रदान करता है:

  • ग्राफ़िक्स प्रोसेसिंग यूनिट (जीपीयू)
  • डिजिटल सिग्नल प्रोसेसर (डीएसपी)
  • तंत्रिका प्रसंस्करण इकाई (एनपीयू)

डिवाइस पर उपलब्ध विशिष्ट हार्डवेयर के आधार पर प्रदर्शन अलग-अलग होगा।

यह पृष्ठ वर्णन करता है कि जावा और कोटलिन में टेन्सरफ्लो लाइट इंटरप्रेटर के साथ एनएनएपीआई प्रतिनिधि का उपयोग कैसे करें। Android C API के लिए, कृपया Android नेटिव डेवलपर किट दस्तावेज़ देखें।

अपने स्वयं के मॉडल पर एनएनएपीआई प्रतिनिधि को आज़माना

ग्रैडल आयात

एनएनएपीआई प्रतिनिधि टेन्सरफ्लो लाइट एंड्रॉइड दुभाषिया का हिस्सा है, जो 1.14.0 या उच्चतर रिलीज़ है। आप अपने मॉड्यूल ग्रेडल फ़ाइल में निम्नलिखित जोड़कर इसे अपने प्रोजेक्ट में आयात कर सकते हैं:

dependencies {
   implementation 'org.tensorflow:tensorflow-lite:+'
}

एनएनएपीआई प्रतिनिधि को आरंभ करना

TensorFlow Lite दुभाषिया को आरंभ करने से पहले NNAPI प्रतिनिधि को आरंभ करने के लिए कोड जोड़ें।

Kotlin

import android.content.res.AssetManager
import org.tensorflow.lite.Interpreter
import org.tensorflow.lite.nnapi.NnApiDelegate
import java.io.FileInputStream
import java.io.IOException
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
...

val options = Interpreter.Options()
var nnApiDelegate: NnApiDelegate? = null
// Initialize interpreter with NNAPI delegate for Android Pie or above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    nnApiDelegate = NnApiDelegate()
    options.addDelegate(nnApiDelegate)
}
val assetManager = assets

// Initialize TFLite interpreter
val tfLite: Interpreter
try {
    tfLite = Interpreter(loadModelFile(assetManager, "model.tflite"), options)
} catch (e: Exception) {
    throw RuntimeException(e)
}

// Run inference
// ...

// Unload delegate
tfLite.close()
nnApiDelegate?.close()

...

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, modelFilename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(modelFilename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}

...

जावा

import android.content.res.AssetManager;
import org.tensorflow.lite.Interpreter;
import org.tensorflow.lite.nnapi.NnApiDelegate;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
...

Interpreter.Options options = (new Interpreter.Options());
NnApiDelegate nnApiDelegate = null;
// Initialize interpreter with NNAPI delegate for Android Pie or above
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    nnApiDelegate = new NnApiDelegate();
    options.addDelegate(nnApiDelegate);
}

AssetManager assetManager = getAssets();
// Initialize TFLite interpreter
try {
    tfLite = new Interpreter(loadModelFile(assetManager, "model.tflite"), options);
} catch (Exception e) {
    throw new RuntimeException(e);
}

// Run inference
// ...

// Unload delegate
tfLite.close();
if(null != nnApiDelegate) {
    nnApiDelegate.close();
}

...

private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelFilename) throws IOException {
    AssetFileDescriptor fileDescriptor = assetManager.openFd(modelFilename);
    FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
    FileChannel fileChannel = inputStream.getChannel();
    long startOffset = fileDescriptor.getStartOffset();
    long declaredLength = fileDescriptor.getDeclaredLength();
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}

...

सर्वोत्तम प्रथाएं

तैनाती से पहले प्रदर्शन का परीक्षण करें

मॉडल आर्किटेक्चर, आकार, संचालन, हार्डवेयर उपलब्धता और रनटाइम हार्डवेयर उपयोग के कारण रनटाइम प्रदर्शन महत्वपूर्ण रूप से भिन्न हो सकता है। उदाहरण के लिए, यदि कोई ऐप रेंडरिंग के लिए GPU का भारी उपयोग करता है, तो संसाधन विवाद के कारण NNAPI त्वरण प्रदर्शन में सुधार नहीं कर सकता है। हम अनुमान समय मापने के लिए डिबग लॉगर का उपयोग करके एक सरल प्रदर्शन परीक्षण चलाने की सलाह देते हैं। उत्पादन में एनएनएपीआई को सक्षम करने से पहले विभिन्न चिपसेट (निर्माता या एक ही निर्माता के मॉडल) वाले कई फोन पर परीक्षण चलाएं जो आपके उपयोगकर्ता आधार के प्रतिनिधि हैं।

उन्नत डेवलपर्स के लिए, TensorFlow Lite एंड्रॉइड के लिए एक मॉडल बेंचमार्क टूल भी प्रदान करता है।

डिवाइस बहिष्करण सूची बनाएं

उत्पादन में, ऐसे मामले हो सकते हैं जहां एनएनएपीआई उम्मीद के मुताबिक प्रदर्शन नहीं करता है। हम डेवलपर्स को उन उपकरणों की एक सूची बनाए रखने की सलाह देते हैं जिन्हें विशेष मॉडलों के साथ संयोजन में एनएनएपीआई त्वरण का उपयोग नहीं करना चाहिए। आप यह सूची "ro.board.platform" के मान के आधार पर बना सकते हैं, जिसे आप निम्नलिखित कोड स्निपेट का उपयोग करके पुनः प्राप्त कर सकते हैं:

String boardPlatform = "";

try {
    Process sysProcess =
        new ProcessBuilder("/system/bin/getprop", "ro.board.platform").
        redirectErrorStream(true).start();

    BufferedReader reader = new BufferedReader
        (new InputStreamReader(sysProcess.getInputStream()));
    String currentLine = null;

    while ((currentLine=reader.readLine()) != null){
        boardPlatform = line;
    }
    sysProcess.destroy();
} catch (IOException e) {}

Log.d("Board Platform", boardPlatform);

उन्नत डेवलपर्स के लिए, दूरस्थ कॉन्फ़िगरेशन सिस्टम के माध्यम से इस सूची को बनाए रखने पर विचार करें। TensorFlow टीम इष्टतम NNAPI कॉन्फ़िगरेशन की खोज और उसे लागू करने को सरल और स्वचालित करने के तरीकों पर सक्रिय रूप से काम कर रही है।

परिमाणीकरण

गणना के लिए 32-बिट फ़्लोट्स के बजाय 8-बिट पूर्णांक या 16-बिट फ़्लोट्स का उपयोग करके क्वांटाइज़ेशन मॉडल आकार को कम कर देता है। 8-बिट पूर्णांक मॉडल आकार 32-बिट फ़्लोट संस्करणों का एक चौथाई है; 16-बिट फ़्लोट्स आधे आकार के होते हैं। परिमाणीकरण से प्रदर्शन में उल्लेखनीय सुधार हो सकता है, हालांकि यह प्रक्रिया कुछ मॉडल सटीकता को कम कर सकती है।

प्रशिक्षण के बाद कई प्रकार की परिमाणीकरण तकनीकें उपलब्ध हैं, लेकिन, वर्तमान हार्डवेयर पर अधिकतम समर्थन और त्वरण के लिए, हम पूर्ण पूर्णांक परिमाणीकरण की अनुशंसा करते हैं। यह दृष्टिकोण भार और संचालन दोनों को पूर्णांकों में परिवर्तित करता है। इस परिमाणीकरण प्रक्रिया को काम करने के लिए एक प्रतिनिधि डेटासेट की आवश्यकता होती है।

समर्थित मॉडल और ऑप्स का उपयोग करें

यदि एनएनएपीआई प्रतिनिधि किसी मॉडल में कुछ ऑप्स या पैरामीटर संयोजनों का समर्थन नहीं करता है, तो फ्रेमवर्क केवल त्वरक पर ग्राफ़ के समर्थित भागों को चलाता है। शेष भाग सीपीयू पर चलता है, जिसके परिणामस्वरूप विभाजन निष्पादन होता है। सीपीयू/त्वरक सिंक्रनाइज़ेशन की उच्च लागत के कारण, अकेले सीपीयू पर पूरे नेटवर्क को निष्पादित करने की तुलना में इसका प्रदर्शन धीमा हो सकता है।

एनएनएपीआई सबसे अच्छा प्रदर्शन करता है जब मॉडल केवल समर्थित ऑप्स का उपयोग करते हैं। निम्नलिखित मॉडल एनएनएपीआई के साथ संगत माने जाते हैं:

जब मॉडल में गतिशील रूप से आकार के आउटपुट होते हैं तो एनएनएपीआई त्वरण भी समर्थित नहीं होता है। इस मामले में, आपको एक चेतावनी मिलेगी जैसे:

ERROR: Attempting to use a delegate that only supports static-sized tensors \
with a graph that has dynamic-sized tensors.

एनएनएपीआई सीपीयू कार्यान्वयन सक्षम करें

एक ग्राफ जिसे त्वरक द्वारा पूरी तरह से संसाधित नहीं किया जा सकता है वह एनएनएपीआई सीपीयू कार्यान्वयन पर वापस आ सकता है। हालाँकि, चूंकि यह आमतौर पर TensorFlow दुभाषिया की तुलना में कम प्रदर्शन करने वाला है, इसलिए यह विकल्प एंड्रॉइड 10 (एपीआई स्तर 29) या इसके बाद के संस्करण के लिए एनएनएपीआई प्रतिनिधि में डिफ़ॉल्ट रूप से अक्षम है। इस व्यवहार को ओवरराइड करने के लिए, NnApiDelegate.Options ऑब्जेक्ट में setUseNnapiCpu को true पर सेट करें।