마이크로컨트롤러 시작하기

이 문서에서는 모델을 학습시키고 다음을 사용하여 추론을 실행하는 방법을 설명합니다. 마이크로컨트롤러에 따라 다릅니다.

Hello World 예시

Hello World 이 예시는 LiteRT 사용의 절대적인 기본 사항을 보여주도록 고안되었습니다. 마이크로컨트롤러용이죠. 사인 함수를 복제하는 모델을 학습시키고 실행합니다. 즉, 숫자 하나를 입력으로 취하고 sine 값. 배포 시 마이크로컨트롤러의 경우, 그 예측은 LED를 깜박이거나 애니메이션을 적용할 수 있습니다.

엔드 투 엔드 워크플로에는 다음 단계가 포함됩니다.

  1. 모델 학습 (Python): 학습, 변환할 Python 파일입니다. 기기 내 사용을 위해 모델을 최적화할 수 있습니다.
  2. 추론 실행 (C++ 17): 다음을 실행하는 엔드 투 엔드 단위 테스트입니다. C++ 라이브러리를 사용하여 모델에서 추론을 실행합니다.

지원되는 기기 받기

사용할 예시 애플리케이션은 다음 기기에서 테스트되었습니다.

지원되는 플랫폼 자세히 알아보기: 마이크로컨트롤러용 LiteRT입니다.

모델 학습

사용 train.py 사인파 인식용 Hello World 모델 학습용

실행: 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님, LiteRT를 사용하여 추론을 실행하는 방법을 보여주는 단위 테스트 마이크로컨트롤러. 모델을 로드하고 추론을 여러 번 실행합니다.

1. 라이브러리 헤더 포함

LiteRT for Microcontrollers 라이브러리를 사용하려면 다음 헤더 파일:

#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. 모델 헤더 포함

LiteRT for Microcontrollers 인터프리터는 모델이 다음과 같을 것으로 예상합니다. C++ 배열로 제공됩니다. 모델은 model.hmodel.cc 파일에 정의되어 있습니다. 헤더에는 다음 행이 포함됩니다.

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

3. 단위 테스트 프레임워크 헤더 포함

단위 테스트를 만들기 위해 다음 줄을 포함하여 마이크로컨트롤러 단위 테스트 프레임워크

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

열거형 값 kTfLiteFloat32는 LiteRT 중 하나에 관한 참조입니다. 데이터 유형이며 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, kTfLiteOkkTfLiteError입니다.

다음 코드는 값이 kTfLiteOk라고 어설션합니다. 즉, 추론이 다음과 같음을 의미합니다. 실행할 수 있습니다

TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status);

13. 출력 얻기

모델의 출력 텐서는 다음에서 output(0)를 호출하여 가져올 수 있습니다. tflite::MicroInterpreter, 여기서 0는 첫 번째 (유일한) 출력을 나타냅니다. 텐서가 포함됩니다.

이 예시에서 모델의 출력은 2차원 텐서 내에서:

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