এই নথিটি ব্যাখ্যা করে কিভাবে একটি মডেলকে প্রশিক্ষণ দিতে হয় এবং একটি মাইক্রোকন্ট্রোলার ব্যবহার করে অনুমান চালাতে হয়।
হ্যালো ওয়ার্ল্ড উদাহরণ
হ্যালো ওয়ার্ল্ড উদাহরণটি মাইক্রোকন্ট্রোলারের জন্য LiteRT ব্যবহার করার সম্পূর্ণ মৌলিক বিষয়গুলি প্রদর্শন করার জন্য ডিজাইন করা হয়েছে। আমরা একটি মডেলকে প্রশিক্ষণ দিই এবং চালাই যা একটি সাইন ফাংশনকে প্রতিলিপি করে, অর্থাৎ, এটি একটি একক সংখ্যা তার ইনপুট হিসাবে নেয় এবং সংখ্যাটির সাইন মান বের করে। মাইক্রোকন্ট্রোলারে মোতায়েন করা হলে, এর ভবিষ্যদ্বাণীগুলি হয় LED ব্লিঙ্ক করতে বা অ্যানিমেশন নিয়ন্ত্রণ করতে ব্যবহৃত হয়।
এন্ড-টু-এন্ড ওয়ার্কফ্লোতে নিম্নলিখিত পদক্ষেপগুলি জড়িত:
- একটি মডেলকে প্রশিক্ষণ দিন (পাইথনে): ডিভাইসে ব্যবহারের জন্য একটি মডেলকে প্রশিক্ষণ, রূপান্তর এবং অপ্টিমাইজ করার জন্য একটি পাইথন ফাইল।
- অনুমান চালান (C++ 17-এ): একটি এন্ড-টু-এন্ড ইউনিট পরীক্ষা যা C++ লাইব্রেরি ব্যবহার করে মডেলে অনুমান চালায়।
একটি সমর্থিত ডিভাইস পান
আমরা যে উদাহরণ অ্যাপ্লিকেশনটি ব্যবহার করব তা নিম্নলিখিত ডিভাইসগুলিতে পরীক্ষা করা হয়েছে:
- Arduino Nano 33 BLE সেন্স (Arduino IDE ব্যবহার করে)
- স্পার্কফান এজ (সরাসরি উত্স থেকে বিল্ডিং)
- STM32F746 ডিসকভারি কিট (Mbed ব্যবহার করে)
- Adafruit EdgeBadge (Arduino IDE ব্যবহার করে)
- মাইক্রোকন্ট্রোলার কিটের জন্য Adafruit LiteRT (Arduino IDE ব্যবহার করে)
- Adafruit সার্কিট খেলার মাঠ ব্লুফ্রুট (Arduino IDE ব্যবহার করে)
- Espressif ESP32-DevKitC (ESP IDF ব্যবহার করে)
- Espressif ESP-EYE (ESP IDF ব্যবহার করে)
মাইক্রোকন্ট্রোলারের জন্য LiteRT- এ সমর্থিত প্ল্যাটফর্ম সম্পর্কে আরও জানুন।
একটি মডেল প্রশিক্ষণ
সিনওয়েভ স্বীকৃতির জন্য হ্যালো ওয়ার্ল্ড মডেল প্রশিক্ষণের জন্য 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
এর নির্দেশাবলী অনুসরণ করব:
নিম্নলিখিত বিভাগগুলি উদাহরণের evaluate_test.cc
, ইউনিট পরীক্ষা যা মাইক্রোকন্ট্রোলারের জন্য LiteRT ব্যবহার করে কীভাবে অনুমান চালাতে হয় তা প্রদর্শন করে। এটি মডেল লোড করে এবং বেশ কয়েকবার অনুমান চালায়।
1. লাইব্রেরি হেডার অন্তর্ভুক্ত করুন
মাইক্রোকন্ট্রোলার লাইব্রেরির জন্য LiteRT ব্যবহার করতে, আমাদের অবশ্যই নিম্নলিখিত হেডার ফাইলগুলি অন্তর্ভুক্ত করতে হবে:
#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
LiteRTFlatBuffer
মডেল ফাইল ফরম্যাটের স্কিমা রয়েছে। -
version.h
LiteRT স্কিমার জন্য সংস্করণ তথ্য প্রদান করে।
2. মডেল হেডার অন্তর্ভুক্ত করুন
মাইক্রোকন্ট্রোলার ইন্টারপ্রেটারের জন্য LiteRT মডেলটিকে C++ অ্যারে হিসাবে সরবরাহ করা হবে বলে আশা করে। মডেলটিকে model.h
এবং model.cc
ফাইলে সংজ্ঞায়িত করা হয়েছে। শিরোনামটি নিম্নলিখিত লাইনের সাথে অন্তর্ভুক্ত করা হয়েছে:
#include "tensorflow/lite/micro/examples/hello_world/model.h"
3. ইউনিট টেস্ট ফ্রেমওয়ার্ক হেডার অন্তর্ভুক্ত করুন
একটি ইউনিট পরীক্ষা তৈরি করার জন্য, আমরা নিম্নলিখিত লাইনটি অন্তর্ভুক্ত করে মাইক্রোকন্ট্রোলার ইউনিট পরীক্ষার কাঠামোর জন্য LiteRT অন্তর্ভুক্ত করি:
#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 = µ_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. মেমরি বরাদ্দ
ইনপুট, আউটপুট এবং মধ্যবর্তী অ্যারেগুলির জন্য আমাদের একটি নির্দিষ্ট পরিমাণ মেমরি আগে থেকে বরাদ্দ করতে হবে। এটি tensor_arena_size
আকারের একটি uint8_t
অ্যারে হিসাবে সরবরাহ করা হয়েছে :
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
হল LiteRT ডেটা প্রকারের একটির একটি রেফারেন্স, এবং common.h
.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);