Mikrodenetleyicileri kullanmaya başlama

Bu belgede, model eğitme ve mikrodenetleyici kullanarak çıkarım yapma açıklanmaktadır.

Hello World örneği

Hello World örneği, Mikrodenetleyiciler için TensorFlow Lite kullanımının mutlak temellerini göstermek için tasarlanmıştır. Bir sinüs işlevini çoğaltan (yani, girdi olarak tek bir sayı alan ve sayının sinüs değerini veren bir model eğitip çalıştırırız). Mikrodenetleyiciye dağıtıldığında, tahminleri LED'leri yanıp söndürmek veya bir animasyonu kontrol etmek için kullanılır.

Uçtan uca iş akışı aşağıdaki adımları içerir:

  1. Model eğitme (Python'da): Bir modeli cihaz üzerinde kullanım için eğitmek, dönüştürmek ve optimize etmek için kullanılan bir python dosyasıdır.
  2. Çıkarım çalıştırma (C++ 17'de): C++ kitaplığını kullanarak model üzerinde çıkarım yapan bir uçtan uca birim testi.

Desteklenen bir cihaz edinin

Kullanacağımız örnek uygulama aşağıdaki cihazlarda test edilmiştir:

Mikrodenetleyiciler için TensorFlow Lite'ta desteklenen platformlar hakkında daha fazla bilgi edinin.

Model eğitin

Sinwave tanıma amacıyla hello world modeli eğitimi için train.py uygulamasını kullanın

Çalıştırma: 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/

Çıkarımı çalıştır

Modeli cihazınızda çalıştırmak için README.md'deki talimatları uygulayacağız:

Merhaba Dünya README.md

Aşağıdaki bölümlerde, örneğin evaluate_test.cc birim testi adım adım açıklamalıdır. Bu test, Mikrodenetleyiciler için TensorFlow Lite'ı kullanarak nasıl çıkarım yapılacağını gösterir. Modeli yükler ve birkaç kez çıkarım yapar.

1. Kitaplık başlıklarını dahil et

Mikrodenetleyiciler için TensorFlow Lite kitaplığını kullanmak için aşağıdaki başlık dosyalarını eklememiz gerekir:

#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. Model başlığını ekleyin

Mikrodenetleyiciler için TensorFlow Lite yorumlayıcısı, modelin bir C++ dizisi olarak sağlanmasını bekler. Model, model.h ve model.cc dosyalarında tanımlı. Üstbilgi, aşağıdaki satıra eklenir:

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

3. Birim test çerçevesi başlığını dahil etme

Birim testi oluşturmak için aşağıdaki satırı ekleyerek Mikrodenetleyiciler için TensorFlow Lite birim test çerçevesini ekliyoruz:

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

Test, aşağıdaki makrolar kullanılarak tanımlanır:

TF_LITE_MICRO_TESTS_BEGIN

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

TF_LITE_MICRO_TESTS_END

Şimdi, yukarıdaki makroda yer alan kodu ele alacağız.

4. Günlük kaydını ayarlama

Günlük kaydını ayarlamak amacıyla, tflite::MicroErrorReporter örneğine işaret eden bir tflite::ErrorReporter işaretçisi oluşturulur:

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

Bu değişken, günlük yazmasına olanak tanıyan yorumlayıcıya iletilir. Mikrodenetleyiciler genellikle günlük kaydı için çeşitli mekanizmalara sahip olduğundan tflite::MicroErrorReporter uygulaması, cihazınıza özel olacak şekilde tasarlanmıştır.

5. Model yükle

Aşağıdaki kodda model, model.h içinde tanımlanan char dizisindeki (g_model) veriler kullanılarak örneklenir. Daha sonra, şema sürümünün kullandığımız sürümle uyumlu olduğundan emin olmak için modeli kontrol ederiz:

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. Örnek işlem çözümleyicisi

Bir MicroMutableOpResolver örneği bildirildi. Çevirmen, modelin kullandığı işlemleri kaydedip bunlara erişmek için bu değeri kullanır:

using HelloWorldOpResolver = tflite::MicroMutableOpResolver<1>;

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

MicroMutableOpResolver, kaydedilecek işlem sayısını belirten bir şablon parametresi gerektirir. RegisterOps işlevi, işlemleri çözümleyiciye kaydeder.

HelloWorldOpResolver op_resolver;
TF_LITE_ENSURE_STATUS(RegisterOps(op_resolver));

7. Bellek tahsis et

Giriş, çıkış ve ara diziler için belirli bir miktarda belleği önceden ayırmamız gerekir. Bu değer, tensor_arena_size boyutunda uint8_t dizisi olarak sağlanır:

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

Gereken boyut, kullandığınız modele bağlıdır ve denemelerle belirlenmesi gerekebilir.

8. Çevirmeni örneklendirme

Daha önce oluşturulan değişkenleri ileterek bir tflite::MicroInterpreter örneği oluştururuz:

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

9. Tensör ayır

Çevirmene, modelin tensörleri için tensor_arena öğesinden bellek ayırmasını söyleriz:

interpreter.AllocateTensors();

10. Giriş şeklini doğrulama

MicroInterpreter örneği, .input(0) yöntemini çağırarak bize modelin giriş tensörüne bir işaretçi sağlayabilir. Burada 0, ilk (ve tek) giriş tensörünü temsil eder:

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

Daha sonra, şeklinin ve türünün beklediğimiz gibi olduğunu doğrulamak için bu tensörü inceleriz:

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

kTfLiteFloat32 sıralama değeri, TensorFlow Lite veri türlerinden birine referanstır ve common.h içinde tanımlanır.

11. Giriş değeri girin

Modele giriş sağlamak için giriş tensörünün içeriğini aşağıdaki gibi ayarlarız:

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

Bu örnekte, 0 değerini temsil eden bir kayan nokta değeri giriyoruz.

12. Modeli çalıştırma

Modeli çalıştırmak için tflite::MicroInterpreter örneğimizde Invoke() öğesini çağırabiliriz:

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

Çalıştırmanın başarılı olup olmadığını belirlemek için döndürülen değeri (TfLiteStatus) kontrol edebiliriz. common.h içinde tanımlanan olası TfLiteStatus değerleri kTfLiteOk ve kTfLiteError'dir.

Aşağıdaki kod, değerin kTfLiteOk olduğunu, yani çıkarımın başarıyla çalıştırıldığını iddia eder.

TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status);

13. Çıkışı alma

Modelin çıkış tensörü, tflite::MicroInterpreter üzerinde output(0) çağrısı yapılarak elde edilebilir. Burada 0, ilk (ve tek) çıkış tensörünü temsil eder.

Bu örnekte, modelin çıkışı, 2D tensör içinde bulunan tek bir kayan nokta değeridir:

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

Değeri doğrudan çıkış tensöründen okuyabilir ve bunun beklediğimiz olduğunu iddia edebiliriz:

// 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. Çıkarımı tekrar çalıştır

Kodun geri kalanı, birkaç kez daha çıkarım yapar. Her örnekte giriş tensörüne bir değer atar, yorumlayıcıyı çağırır ve sonucu çıkış tensöründen okuruz:

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