माइक्रोकंट्रोलर के साथ शुरुआत करें

यह दस्तावेज़ बताता है कि किसी मॉडल को कैसे प्रशिक्षित किया जाए और माइक्रोकंट्रोलर का उपयोग करके अनुमान कैसे लगाया जाए।

हैलो वर्ल्ड उदाहरण

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

एंड-टू-एंड वर्कफ़्लो में निम्नलिखित चरण शामिल हैं:

  1. एक मॉडल को प्रशिक्षित करें (पायथन में): ऑन-डिवाइस उपयोग के लिए एक मॉडल को प्रशिक्षित, परिवर्तित और अनुकूलित करने के लिए एक पायथन फ़ाइल।
  2. रन अनुमान (C++ 17 में): एक एंड-टू-एंड यूनिट टेस्ट जो C++ लाइब्रेरी का उपयोग करके मॉडल पर अनुमान चलाता है।

एक समर्थित उपकरण प्राप्त करें

हम जिस उदाहरण एप्लिकेशन का उपयोग कर रहे हैं उसका निम्नलिखित उपकरणों पर परीक्षण किया गया है:

माइक्रोकंट्रोलर्स के लिए TensorFlow Lite में समर्थित प्लेटफॉर्म के बारे में और जानें।

एक मॉडल को प्रशिक्षित करें

sinwave पहचान के लिए हैलो वर्ल्ड मॉडल प्रशिक्षण के लिए train.py का उपयोग करें

चलाएँ: bazel build tensorflow/lite/micro/examples/hello_world:train bazel-bin/tensorflow/lite/micro/examples/hello_world/train --save_tf_model --save_dir=/tmp/model_created/

अनुमान चलाओ

आपके डिवाइस पर मॉडल को चलाने के लिए, हम README.md में दिए गए निर्देशों का पालन करेंगे:

हैलो वर्ल्ड README.md

निम्नलिखित खंड उदाहरण के evaluate_test.cc , इकाई परीक्षण के माध्यम से चलते हैं जो दर्शाता है कि माइक्रोकंट्रोलर्स के लिए टेन्सरफ्लो लाइट का उपयोग करके अनुमान कैसे चलाया जाए। यह मॉडल को लोड करता है और कई बार अनुमान लगाता है।

1. लाइब्रेरी हेडर शामिल करें

माइक्रोकंट्रोलर्स लाइब्रेरी के लिए TensorFlow Lite का उपयोग करने के लिए, हमें निम्नलिखित हेडर फाइलों को शामिल करना होगा:

#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/version.h"
  • micro_mutable_op_resolver.h मॉडल चलाने के लिए दुभाषिया द्वारा उपयोग किए जाने वाले संचालन प्रदान करता है।
  • micro_error_reporter.h डीबग जानकारी आउटपुट करता है।
  • micro_interpreter.h में मॉडल लोड करने और चलाने के लिए कोड होता है।
  • schema_generated.h में TensorFlow Lite FlatBuffer मॉडल फ़ाइल स्वरूप के लिए स्कीमा शामिल है।
  • version.h TensorFlow Lite स्कीमा के लिए संस्करण संबंधी जानकारी प्रदान करता है।

2. मॉडल हैडर शामिल करें

माइक्रोकंट्रोलर्स दुभाषिया के लिए TensorFlow Lite मॉडल को C++ सरणी के रूप में प्रदान किए जाने की अपेक्षा करता है। मॉडल को model.h और model.cc फ़ाइलों में परिभाषित किया गया है। शीर्षलेख निम्न पंक्ति के साथ शामिल है:

#include "tensorflow/lite/micro/examples/hello_world/model.h"

3. यूनिट टेस्ट फ्रेमवर्क हेडर शामिल करें

एक इकाई परीक्षण बनाने के लिए, हम निम्न पंक्ति को शामिल करके माइक्रोकंट्रोलर्स इकाई परीक्षण ढांचे के लिए TensorFlow Lite शामिल करते हैं:

#include "tensorflow/lite/micro/testing/micro_test.h"

परीक्षण को निम्नलिखित मैक्रोज़ का उपयोग करके परिभाषित किया गया है:

TF_LITE_MICRO_TESTS_BEGIN

TF_LITE_MICRO_TEST(LoadModelAndPerformInference) {
  . // add code here
  .
}

TF_LITE_MICRO_TESTS_END

अब हम उपरोक्त मैक्रो में शामिल कोड पर चर्चा करते हैं।

4. लॉगिंग सेट करें

लॉगिंग सेट अप करने के लिए, एक tflite::ErrorReporter पॉइंटर एक tflite::MicroErrorReporter उदाहरण के लिए पॉइंटर का उपयोग करके बनाया गया है:

tflite::MicroErrorReporter micro_error_reporter;
tflite::ErrorReporter* error_reporter = &micro_error_reporter;

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

5. एक मॉडल लोड करें

निम्नलिखित कोड में, मॉडल को char सरणी, g_model से डेटा का उपयोग करके तत्काल किया जाता है, जिसे model.h में घोषित किया जाता है। फिर हम यह सुनिश्चित करने के लिए मॉडल की जांच करते हैं कि इसका स्कीमा संस्करण हमारे द्वारा उपयोग किए जा रहे संस्करण के अनुकूल है:

const tflite::Model* model = ::tflite::GetModel(g_model);
if (model->version() != TFLITE_SCHEMA_VERSION) {
  TF_LITE_REPORT_ERROR(error_reporter,
      "Model provided is schema version %d not equal "
      "to supported version %d.\n",
      model->version(), TFLITE_SCHEMA_VERSION);
}

6. तत्काल संचालन रिज़ॉल्वर

एक MicroMutableOpResolver उदाहरण घोषित किया गया है। इसका उपयोग दुभाषिया द्वारा मॉडल द्वारा उपयोग किए जाने वाले संचालन को पंजीकृत करने और एक्सेस करने के लिए किया जाएगा:

using HelloWorldOpResolver = tflite::MicroMutableOpResolver<1>;

TfLiteStatus RegisterOps(HelloWorldOpResolver& op_resolver) {
  TF_LITE_ENSURE_STATUS(op_resolver.AddFullyConnected());
  return kTfLiteOk;

MicroMutableOpResolver को एक टेम्प्लेट पैरामीटर की आवश्यकता होती है जो पंजीकृत होने वाले ऑप्स की संख्या को दर्शाता है। RegisterOps फ़ंक्शन रिज़ॉल्वर के साथ ऑप्स को पंजीकृत करता है।

HelloWorldOpResolver op_resolver;
TF_LITE_ENSURE_STATUS(RegisterOps(op_resolver));

7. मेमोरी आवंटित करें

हमें इनपुट, आउटपुट और इंटरमीडिएट सरणियों के लिए एक निश्चित मात्रा में मेमोरी का पूर्व-आवंटन करने की आवश्यकता है। यह आकार के uint8_t सरणी के रूप में प्रदान किया गया है tensor_arena_size :

const int tensor_arena_size = 2 * 1024;
uint8_t tensor_arena[tensor_arena_size];

आवश्यक आकार आपके द्वारा उपयोग किए जा रहे मॉडल पर निर्भर करेगा, और प्रयोग द्वारा निर्धारित करने की आवश्यकता हो सकती है।

8. दुभाषिया को तत्काल करें

हम एक tflite::MicroInterpreter उदाहरण बनाते हैं, जो पहले बनाए गए वेरिएबल्स में गुजरता है:

tflite::MicroInterpreter interpreter(model, resolver, tensor_arena,
                                     tensor_arena_size, error_reporter);

9. टेंसर आवंटित करें

हम दुभाषिया को मॉडल के टेंसर के लिए tensor_arena से मेमोरी आवंटित करने के लिए कहते हैं:

interpreter.AllocateTensors();

10. इनपुट आकार को मान्य करें

MicroInterpreter उदाहरण हमें .input(0) पर कॉल करके मॉडल के इनपुट टेंसर के लिए पॉइंटर प्रदान कर सकता है, जहां 0 पहले (और केवल) इनपुट टेंसर का प्रतिनिधित्व करता है:

  // Obtain a pointer to the model's input tensor
  TfLiteTensor* input = interpreter.input(0);

इसके बाद हम इस टेन्सर का निरीक्षण यह सुनिश्चित करने के लिए करते हैं कि इसका आकार और प्रकार वही है जिसकी हम अपेक्षा कर रहे हैं:

// Make sure the input has the properties we expect
TF_LITE_MICRO_EXPECT_NE(nullptr, input);
// The property "dims" tells us the tensor's shape. It has one element for
// each dimension. Our input is a 2D tensor containing 1 element, so "dims"
// should have size 2.
TF_LITE_MICRO_EXPECT_EQ(2, input->dims->size);
// The value of each element gives the length of the corresponding tensor.
// We should expect two single element tensors (one is contained within the
// other).
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[0]);
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[1]);
// The input is a 32 bit floating point value
TF_LITE_MICRO_EXPECT_EQ(kTfLiteFloat32, input->type);

Enum मान kTfLiteFloat32 TensorFlow Lite डेटा प्रकारों में से एक का संदर्भ है, और इसे common.h में परिभाषित किया गया है।

11. एक इनपुट मूल्य प्रदान करें

मॉडल को इनपुट प्रदान करने के लिए, हम इनपुट टेंसर की सामग्री को निम्नानुसार सेट करते हैं:

input->data.f[0] = 0.;

इस मामले में, हम 0 का प्रतिनिधित्व करने वाला एक फ़्लोटिंग पॉइंट मान इनपुट करते हैं।

12. मॉडल चलाएँ

मॉडल को चलाने के लिए, हम अपने tflite::MicroInterpreter उदाहरण पर Invoke() कॉल कर सकते हैं:

TfLiteStatus invoke_status = interpreter.Invoke();
if (invoke_status != kTfLiteOk) {
  TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed\n");
}

रन सफल रहा या नहीं, यह निर्धारित करने के लिए हम रिटर्न वैल्यू, TfLiteStatus की जांच कर सकते हैं। TfLiteStatus के संभावित मान, जो common.h में परिभाषित हैं, kTfLiteOk और kTfLiteError हैं।

निम्नलिखित कोड का दावा है कि मान kTfLiteOk है, जिसका अर्थ है कि अनुमान सफलतापूर्वक चलाया गया था।

TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status);

13. आउटपुट प्राप्त करें

मॉडल का आउटपुट टेंसर tflite::MicroInterpreter पर output(0) कॉल करके प्राप्त किया जा सकता है, जहां 0 पहले (और केवल) आउटपुट टेंसर का प्रतिनिधित्व करता है।

उदाहरण में, मॉडल का आउटपुट 2D टेन्सर के भीतर समाहित एकल फ़्लोटिंग पॉइंट मान है:

TfLiteTensor* output = interpreter.output(0);
TF_LITE_MICRO_EXPECT_EQ(2, output->dims->size);
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[0]);
TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[1]);
TF_LITE_MICRO_EXPECT_EQ(kTfLiteFloat32, output->type);

हम आउटपुट टेन्सर से सीधे मान पढ़ सकते हैं और दावा कर सकते हैं कि यह वही है जो हम उम्मीद करते हैं:

// Obtain the output value from the tensor
float value = output->data.f[0];
// Check that the output value is within 0.05 of the expected value
TF_LITE_MICRO_EXPECT_NEAR(0., value, 0.05);

14. फिर से अनुमान चलाएँ

शेष कोड कई बार अनुमान लगाता है। प्रत्येक उदाहरण में, हम इनपुट टेन्सर को एक मान प्रदान करते हैं, दुभाषिया को आमंत्रित करते हैं, और आउटपुट टेंसर से परिणाम पढ़ते हैं:

input->data.f[0] = 1.;
interpreter.Invoke();
value = output->data.f[0];
TF_LITE_MICRO_EXPECT_NEAR(0.841, value, 0.05);

input->data.f[0] = 3.;
interpreter.Invoke();
value = output->data.f[0];
TF_LITE_MICRO_EXPECT_NEAR(0.141, value, 0.05);

input->data.f[0] = 5.;
interpreter.Invoke();
value = output->data.f[0];
TF_LITE_MICRO_EXPECT_NEAR(-0.959, value, 0.05);