Memulai mikrokontroler

Dokumen ini menjelaskan cara melatih model dan menjalankan inferensi menggunakan mikrokontroler.

Contoh Hello World

Contoh Hello World dirancang untuk mendemonstrasikan dasar-dasar penggunaan TensorFlow Lite untuk Mikrokontroler. Kami melatih dan menjalankan model yang mereplikasi fungsi sinus, yaitu, dibutuhkan satu angka sebagai inputnya, dan mengeluarkan nilai sinus angka tersebut. Saat diterapkan ke mikrokontroler, prediksinya digunakan untuk mengedipkan LED atau mengontrol animasi.

Alur kerja end-to-end melibatkan langkah-langkah berikut:

  1. Latih model (dengan Python): File python untuk melatih, mengonversi, dan mengoptimalkan model untuk penggunaan di perangkat.
  2. Jalankan inferensi (dalam C++ 17): Pengujian unit end-to-end yang menjalankan inferensi pada model menggunakan pustaka C++ .

Dapatkan perangkat yang didukung

Aplikasi contoh yang akan kita gunakan telah diuji pada perangkat berikut:

Pelajari selengkapnya tentang platform yang didukung di TensorFlow Lite untuk Mikrokontroler .

Latih seorang model

Gunakan train.py untuk pelatihan model hello world untuk pengenalan sinwave

Jalankan: 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/

Jalankan inferensi

Untuk menjalankan model di perangkat Anda, kami akan menelusuri petunjuk di README.md :

Halo Dunia README.md

Bagian berikut membahas evaluate_test.cc contoh, pengujian unit yang menunjukkan cara menjalankan inferensi menggunakan TensorFlow Lite untuk Mikrokontroler. Itu memuat model dan menjalankan inferensi beberapa kali.

1. Sertakan header perpustakaan

Untuk menggunakan pustaka TensorFlow Lite for Microcontrollers, kita harus menyertakan file header berikut:

#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"

2. Sertakan tajuk model

Interpreter TensorFlow Lite untuk Mikrokontroler mengharapkan model disediakan sebagai larik C++. Model didefinisikan dalam file model.h dan model.cc . Header disertakan dengan baris berikut:

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

3. Sertakan tajuk kerangka pengujian unit

Untuk membuat pengujian unit, kami menyertakan kerangka pengujian unit TensorFlow Lite untuk Mikrokontroler dengan menyertakan baris berikut:

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

Pengujian ditentukan menggunakan makro berikut:

TF_LITE_MICRO_TESTS_BEGIN

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

TF_LITE_MICRO_TESTS_END

Kami sekarang membahas kode yang termasuk dalam makro di atas.

4. Siapkan pencatatan

Untuk menyiapkan logging, pointer tflite::ErrorReporter dibuat menggunakan pointer ke instance tflite::MicroErrorReporter :

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

Variabel ini akan diteruskan ke juru bahasa, yang memungkinkannya menulis log. Karena mikrokontroler sering memiliki berbagai mekanisme untuk logging, penerapan tflite::MicroErrorReporter dirancang untuk disesuaikan dengan perangkat khusus Anda.

5. Muat model

Dalam kode berikut, model dibuat instance-nya menggunakan data dari array char , g_model , yang dideklarasikan dalam model.h . Kami kemudian memeriksa model untuk memastikan versi skemanya kompatibel dengan versi yang kami gunakan:

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. Instansiasi penyelesai operasi

Instance MicroMutableOpResolver dideklarasikan. Ini akan digunakan oleh juru bahasa untuk mendaftar dan mengakses operasi yang digunakan oleh model:

using HelloWorldOpResolver = tflite::MicroMutableOpResolver<1>;

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

MicroMutableOpResolver membutuhkan parameter template yang menunjukkan jumlah operasi yang akan didaftarkan. Fungsi RegisterOps mendaftarkan operasi dengan penyelesai.

HelloWorldOpResolver op_resolver;
TF_LITE_ENSURE_STATUS(RegisterOps(op_resolver));

7. Alokasikan memori

Kita perlu mengalokasikan sejumlah memori untuk input, output, dan array perantara. Ini disediakan sebagai array uint8_t dengan ukuran tensor_arena_size :

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

Ukuran yang diperlukan akan bergantung pada model yang Anda gunakan, dan mungkin perlu ditentukan melalui eksperimen.

8. Instansiasi juru bahasa

Kami membuat instance tflite::MicroInterpreter , meneruskan variabel yang dibuat sebelumnya:

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

9. Alokasikan tensor

Kami memberi tahu juru bahasa untuk mengalokasikan memori dari tensor_arena untuk tensor model:

interpreter.AllocateTensors();

10. Validasi bentuk masukan

Instance MicroInterpreter dapat memberi kita pointer ke tensor input model dengan memanggil .input(0) , di mana 0 mewakili tensor input pertama (dan satu-satunya):

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

Kami kemudian memeriksa tensor ini untuk mengonfirmasi bahwa bentuk dan jenisnya sesuai dengan yang kami harapkan:

// 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);

Nilai enum kTfLiteFloat32 adalah referensi ke salah satu tipe data TensorFlow Lite, dan ditentukan dalam common.h .

11. Berikan nilai masukan

Untuk memberikan input ke model, kami mengatur konten tensor input, sebagai berikut:

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

Dalam hal ini, kami memasukkan nilai floating point yang mewakili 0 .

12. Jalankan modelnya

Untuk menjalankan model, kita dapat memanggil Invoke() pada instance tflite::MicroInterpreter kita:

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

Kita dapat memeriksa nilai kembalian, TfLiteStatus , untuk menentukan apakah proses berhasil. Nilai yang mungkin dari TfLiteStatus , didefinisikan dalam common.h , adalah kTfLiteOk dan kTfLiteError .

Kode berikut menegaskan bahwa nilainya adalah kTfLiteOk , artinya inferensi berhasil dijalankan.

TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status);

13. Dapatkan hasilnya

Tensor output model dapat diperoleh dengan memanggil output(0) pada tflite::MicroInterpreter , di mana 0 mewakili tensor output pertama (dan satu-satunya).

Dalam contoh, keluaran model adalah nilai floating point tunggal yang terkandung dalam tensor 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);

Kita dapat membaca nilainya langsung dari tensor keluaran dan menegaskan bahwa itulah yang kita harapkan:

// 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. Jalankan inferensi lagi

Sisa kode menjalankan inferensi beberapa kali lagi. Dalam setiap contoh, kami menetapkan nilai ke tensor input, memanggil juru bahasa, dan membaca hasil dari tensor output:

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);