Mikrodenetleyicileri kullanmaya başlama

Bu belgede, bir modelin nasıl eğitileceği ve kontrol edebilirsiniz.

Hello World örneği

İlgili içeriği oluşturmak için kullanılan Hello World örneği, LiteRT kullanmanın mutlak temellerini göstermek için tasarlanmıştır kontrol edebilirsiniz. Sinüs fonksiyonunu çoğaltan bir model eğitiyor ve çalıştırıyoruz, Örneğin, giriş olarak tek bir sayı alır ve ilgili sayının çıktısını verir. sinüs değerine ayarlayın. içerdiği tahminler, LED'leri yakıp söndürmek veya bir cihazı kontrol etmek için kullanılır. animasyon ekler.

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

  1. Model eğitme (Python'da): Eğitmek, dönüştürmek için bir python dosyası ve bir modeli cihazda kullanım için optimize edebilirsiniz.
  2. Çıkarım yapma (C++ 17'de): Benzersiz bir çözüm oluşturan uçtan uca C++ kitaplığını kullanarak model üzerinde çıkarım çalıştırır.

Desteklenen bir cihaz edinin

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

Desteklenen platformlar hakkında daha fazla bilgiyi şurada bulabilirsiniz: Mikrodenetleyiciler için LiteRT.

Model eğitin

Tekliflerinizi otomatikleştirmek ve optimize etmek için train.py sinwave tanıma için hello dünya modeli eğitimine yönelik

Ç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 yap

Modeli cihazınızda çalıştırmak için README.md:

Merhaba Dünya README.md

Aşağıdaki bölümlerde bu örnekte evaluate_test.cc için LiteRT kullanarak çıkarım yapıldığını gösteren birim testi Mikrodenetleyiciler Modeli yükler ve çıkarımı birkaç kez çalıştırır.

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

Mikrodenetleyiciler için LiteRT kitaplığını kullanmak istiyorsanız şu başlık dosyalarını kullanabilirsiniz:

#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ı dahil et

Mikrodenetleyiciler için LiteRT yorumlayıcısı, modelin C++ dizisi olarak sağlanır. Model, model.h ve model.cc dosyalarında tanımlanmıştır. Üstbilgi, aşağıdaki satırla birlikte eklenir:

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

3. Birim testi çerçevesi başlığını dahil et

Birim testi oluşturmak için her bir birim için LiteRT'i Mikrodenetleyiciler birim test çerçevesi için aşağıdaki satırı ekleyin:

#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 için işaretçi kullanılarak bir tflite::ErrorReporter işaretçisi oluşturulur. tflite::MicroErrorReporter örneğine ekleme:

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

Bu değişken, yorumcuya iletilerek yazmasına olanak tanır günlükler. Mikrodenetleyiciler genellikle günlük kaydı için çeşitli mekanizmalara sahip olduğundan, tflite::MicroErrorReporter uygulaması, dönüşüm hunisinin üst kısmındaki emin olmanız gerekir.

5. Model yükleme

Aşağıdaki kodda model, bir char dizisindeki veriler kullanılarak örneklendirilir. g_model, model.h dilinde tanımlanır. Daha sonra modeli kontrol ederek kullandığımız sürümle uyumlu olduğunu varsayalım:

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. İşlem çözümleyicisini örneklendirme

CEVAP MicroMutableOpResolver olduğunu varsayalım. Bu bilgi, çevirmen tarafından kayıt ve model tarafından kullanılan işlemlere erişin:

using HelloWorldOpResolver = tflite::MicroMutableOpResolver<1>;

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

MicroMutableOpResolver, değeri belirten bir şablon parametresi gerektirir pek çok işlem vardır. RegisterOps işlevi, işlemleri kaydeder çözmek için kullanılabilmesidir.

HelloWorldOpResolver op_resolver;
TF_LITE_ENSURE_STATUS(RegisterOps(op_resolver));

7. Bellek ayır

Belli bir miktarda bellek miktarını giriş, çıkış ve kontrol için önceden ayırmamız gerekiyor. emin olmaktır. Bu, uint8_t boyut dizisi olarak sağlanır tensor_arena_size:

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 denemeyle belirlenir.

8. Çevirmen gösterme

Değişkenleri ileten bir tflite::MicroInterpreter örneği oluştururuz daha önce oluşturulan:

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

9. Tensör ayırma

Çevirmene, tensor_arena cihazından bellek ayırmasını söyleriz. modelin tensörleri:

interpreter.AllocateTensors();

10. Giriş şeklini doğrula

MicroInterpreter örneği, modelin temel durumunu göstermek için .input(0) çağrısıyla giriş tensörü; burada 0, ilk (ve tek) değeri temsil eder giriş tensörü:

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

Ardından, şeklinin ve türünün neye benzediğini göstermek için bu tensörü inceleriz. beklenen:

// 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 numaralandırma değeri, LiteRT'lerden birine referans ve aşağıdaki koşullarda tanımlanmıştır: common.h

11. Giriş değeri girin

Modele bir giriş sağlamak için giriş tensörünün içeriğini şu şekilde ayarlarız: şöyle olur:

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 numaralı telefondan Invoke() adlı kuruluşu arayabiliriz örnek:

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 TfLiteStatus döndürme değerini kontrol edebiliriz. işidir. Şurada tanımlanan olası TfLiteStatus değerleri: common.h, kTfLiteOk ve kTfLiteError.

Aşağıdaki kod, değerin kTfLiteOk olduğunu doğrular. Çıkarım, yardımcı olabilir.

TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status);

13. Çıktı alma

Modelin çıkış tensörü,output(0) 0 burada ilk (ve tek) çıkışı temsil eder. tflite::MicroInterpreter tensördür.

Örnekte, modelin çıkışı, hedef değerde 2D tensör içinde:

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, kendisinde beklentilerimiz:

// 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ı çıkarımı birkaç kez daha çalıştırır. Her örnekte giriş tensörüne bir değer atar, yorumlayıcıyı çağırır ve şu çıkış tensöründen elde edilir:

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