TensorFlow Lite 추론

용어 추론은 입력 데이터에 기초하여 예측을 위해 온 - 디바이스 TensorFlow 라이트 모델을 실행하는 과정을 말한다. TensorFlow 라이트 모델 추론을 수행하려면, 당신은 통역을 통해 그것을 실행해야합니다. TensorFlow Lite 인터프리터는 간결하고 빠르게 설계되었습니다. 인터프리터는 정적 그래프 순서와 사용자 지정(덜 동적인) 메모리 할당자를 사용하여 로드, 초기화 및 실행 대기 시간을 최소화합니다.

이 페이지는 어떻게 TensorFlow 라이트 인터프리터에 대한 접근에 대해 설명하고 각각에 대해 다른 자원에 C ++, 자바, 파이썬, 플러스 링크를 사용하여 추론을 수행 지원 플랫폼을 .

중요한 개념

TensorFlow Lite 추론은 일반적으로 다음 단계를 따릅니다.

  1. 모델 로드

    당신은로드해야합니다 .tflite 모델의 실행 그래프가 포함되어 메모리에 모델을.

  2. 데이터 변환

    모델의 원시 입력 데이터는 일반적으로 모델에서 예상하는 입력 데이터 형식과 일치하지 않습니다. 예를 들어 이미지 크기를 조정하거나 모델과 호환되도록 이미지 형식을 변경해야 할 수 있습니다.

  3. 추론 실행

    이 단계에는 TensorFlow Lite API를 사용하여 모델을 실행하는 작업이 포함됩니다. 다음 섹션에 설명된 대로 인터프리터 구축 및 텐서 할당과 같은 몇 가지 단계가 포함됩니다.

  4. 출력 해석

    모델 추론에서 결과를 받으면 애플리케이션에 유용한 의미 있는 방식으로 텐서를 해석해야 합니다.

    예를 들어, 모델은 확률 목록만 반환할 수 있습니다. 확률을 관련 범주에 매핑하고 최종 사용자에게 제시하는 것은 귀하에게 달려 있습니다.

지원 플랫폼

TensorFlow 추론 API는 다음과 같은 가장 일반적인 모바일 / 임베디드 플랫폼에 제공되는 안드로이드 , 아이폰 OS리눅스 여러 프로그래밍 언어.

대부분의 경우 API 디자인은 사용 편의성보다 성능에 대한 선호를 반영합니다. TensorFlow Lite는 소형 기기에서 빠른 추론을 위해 설계되었으므로 API가 편의성을 희생하면서 불필요한 사본을 피하려고 시도하는 것은 놀라운 일이 아닙니다. 마찬가지로 TensorFlow API와의 일관성은 명시적인 목표가 아니었으며 언어 간에 약간의 차이가 예상됩니다.

모든 라이브러리에서 TensorFlow Lite API를 사용하면 모델을 로드하고, 입력을 제공하고, 추론 출력을 검색할 수 있습니다.

안드로이드 플랫폼

Android에서 TensorFlow Lite 추론은 Java 또는 C++ API를 사용하여 수행할 수 있습니다. Java API는 편의성을 제공하며 Android Activity 클래스 내에서 직접 사용할 수 있습니다. C++ API는 더 많은 유연성과 속도를 제공하지만 Java와 C++ 계층 간에 데이터를 이동하려면 JNI 래퍼를 작성해야 할 수 있습니다.

사용하는 방법에 대한 자세한 내용은 아래를 참조 C를 ++자바 , 또는 다음과 안드로이드 빠른 시작을 튜토리얼과 예제 코드.

TensorFlow Lite Android 래퍼 코드 생성기

TensorFlow 라이트 모델 강화를 위해 메타 데이터 , 개발자는 플랫폼 특정 래퍼 코드를 생성하기 위해 TensorFlow 라이트 안드로이드 래퍼 코드 생성기를 사용할 수 있습니다. 래퍼 코드와 직접 상호 작용 할 필요가 제거 ByteBuffer 안드로이드에 있습니다. 대신, 개발자는 다음과 같은 타입의 객체로 TensorFlow 라이트 모델과 상호 작용할 수있는 BitmapRect . 자세한 내용을 참조하시기 바랍니다 TensorFlow 라이트 안드로이드 래퍼 코드 생성기 .

iOS 플랫폼

iOS에서, TensorFlow Lite는 작성 네이티브 아이폰 OS 라이브러리를 함께 사용할 수 스위프트목표 - C . 당신은 또한 사용할 수있는 C API를 목표 - C 코드에서 직접.

사용하는 방법에 대한 자세한 내용은 아래를 참조 스위프트 , 오브젝티브 CC API를 , 또는에 따라 아이폰 OS 퀵 스타트 자습서 및 예제 코드를.

리눅스 플랫폼

(포함 Linux 플랫폼에서 라즈베리 파이 ), 당신은 사용할 수 TensorFlow 라이트 API를 사용하여 추론을 실행할 수있는 C ++파이썬을 다음 절에서와 같이.

모델 실행

TensorFlow Lite 모델을 실행하려면 몇 가지 간단한 단계를 거쳐야 합니다.

  1. 모델을 메모리에 로드합니다.
  2. 구축 Interpreter 기존 모델을 기반으로합니다.
  3. 입력 텐서 값을 설정합니다. (미리 정의된 크기가 필요하지 않은 경우 선택적으로 입력 텐서의 크기를 조정합니다.)
  4. 추론을 호출합니다.
  5. 출력 텐서 값을 읽습니다.

다음 섹션에서는 각 언어에서 이러한 단계를 수행하는 방법을 설명합니다.

Java에서 모델 로드 및 실행

플랫폼: 안드로이드

: 그것은 안드로이드 라이브러리 종속성으로 사용할 수 있도록 TensorFlow 라이트와 추론을 실행하기위한 자바 API는 주로, 안드로이드와 함께 사용하도록 설계되었습니다 org.tensorflow:tensorflow-lite .

자바에서는 사용할 것이다 Interpreter 모델 및 드라이브 모델 추론을로드하는 클래스. 대부분의 경우 이것이 필요한 유일한 API일 수 있습니다.

당신은 초기화 할 수 있습니다 Interpreter 사용 .tflite 파일 :

public Interpreter(@NotNull File modelFile);

아니면와 MappedByteBuffer :

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

두 경우 모두, 유효한 TensorFlow 라이트 모델을 제공해야하거나 API가 발생 IllegalArgumentException . 당신이 사용하는 경우 MappedByteBuffer 초기화 Interpreter , 그것의 전체 수명 기간 동안 변경되지 않은 상태로 유지해야한다 Interpreter .

모델에서 추론을 실행하는 기본 방법은 서명을 사용하는 것입니다. - Tensorflow 2.5부터 변환된 모델에 사용 가능

try (Interpreter interpreter = new Interpreter(file_of_tensorflowlite_model)) {
  Map<String, Object> inputs = new HashMap<>();
  inputs.put("input_1", input1);
  inputs.put("input_2", input2);
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("output_1", output1);
  interpreter.runSignature(inputs, outputs, "mySignature");
}

runSignature 방법은 세 가지 인수를 사용합니다 :

  • 입력 : 입력 객체에 서명에 입력 이름에서 입력에 매핑합니다.

  • 출력 : 출력 데이터에 서명 출력 이름 출력 매핑에 대한지도.

  • 서명 이름 [선택] : 서명 이름 (모델이 하나의 서명이있는 경우 비어 가능).

모델에 정의된 서명이 없을 때 추론을 실행하는 또 다른 방법입니다. 간단히 전화 Interpreter.run() . 예를 들어:

try (Interpreter interpreter = new Interpreter(file_of_a_tensorflowlite_model)) {
  interpreter.run(input, output);
}

run() 메소드는 하나 개의 출력 단 하나 개의 입력과 반환합니다. 따라서 모델에 다중 입력 또는 다중 출력이 있는 경우 대신 다음을 사용하십시오.

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

이 경우, 각 항목에 inputs 하는 입력 및 텐서에 대응 map_of_indices_to_outputs 해당 출력 데이터의 출력 텐서의 인덱스를 매핑한다.

두 경우 모두, 텐서 지수는 당신이에게 준 값에 해당한다 TensorFlow 라이트 변환기 당신이 모델을 만들 때. 에서 텐서의 순서주의하십시오 input TensorFlow 라이트 변환기에 주어진 순서와 일치해야합니다.

Interpreter 는 작업 이름을 사용하는 모델의 입력 또는 출력의 인덱스를 취득하는 클래스는 편리한 기능을 제공합니다 :

public int getInputIndex(String opName);
public int getOutputIndex(String opName);

경우 opName 모델의 유효한 작동하지 않습니다, 그것은 발생 IllegalArgumentException .

또한 조심 Interpreter 자원을 소유하고있다. 메모리 누수를 방지하려면 사용 후 리소스를 해제해야 합니다.

interpreter.close();

자바 예제 프로젝트를 들어, 참조 안드로이드 영상 분류 샘플을 .

지원되는 데이터 유형(Java에서)

TensorFlow Lite를 사용하려면 입력 및 출력 텐서의 데이터 유형이 다음 기본 유형 중 하나여야 합니다.

  • float
  • int
  • long
  • byte

String 유형도 지원되지만이 기본 유형과 다르게 인코딩됩니다. 특히 문자열 Tensor의 모양은 Tensor에서 문자열의 수와 배열을 결정하며 각 요소 자체는 가변 길이 문자열입니다. 이러한 의미에서, 텐서 (바이트) 크기는 형상으로부터 계산 만 입력 따라서 문자열은 단일 평면으로 제공 할 수없는 수없는 ByteBuffer 인수.

같은 박스 유형을 포함하여 다른 데이터 유형의 경우 IntegerFloat , 사용, IllegalArgumentException 슬로우됩니다.

입력

각 입력 지원 기본 유형의 배열 또는 다차원 배열 또는 원시되어야 ByteBuffer 적절한 크기. 입력이 배열 또는 다차원 배열인 경우 연결된 입력 텐서는 추론 시간에 배열의 차원으로 암시적으로 크기가 조정됩니다. 입력이있는 경우의 ByteBuffer, 발신자는 먼저 수동 (비아 연관된 입력 텐서의 크기를 조정한다 Interpreter.resizeInput() 추론을 실행하기 전에).

사용시 ByteBuffer 이것은 허용하는, 직접 바이트 버퍼를 사용하여 선호 Interpreter 불필요한 복사를 방지하기 위해. 상기 중간 ByteBuffer 직접 바이트 버퍼이고, 그 순서가 있어야 ByteOrder.nativeOrder() . 모델 추론에 사용한 후에는 모델 추론이 완료될 때까지 변경되지 않은 상태로 유지되어야 합니다.

출력

각 출력은 지원되는 기본 유형의 배열 또는 다차원 배열이거나 적절한 크기의 ByteBuffer여야 합니다. 일부 모델에는 입력에 따라 출력 텐서의 모양이 다를 수 있는 동적 출력이 있습니다. 기존 Java 추론 API로 이를 처리하는 직접적인 방법은 없지만 계획된 확장을 통해 이를 가능하게 할 것입니다.

Swift에서 모델 로드 및 실행

플랫폼: iOS

스위프트 API를 사용할 수 있습니다 TensorFlowLiteSwift Cocoapods에서 포드.

첫째, 당신은 수입에 필요한 TensorFlowLite 모듈.

import TensorFlowLite
// Getting model path
guard
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
else {
  // Error handling...
}

do {
  // Initialize an interpreter with the model.
  let interpreter = try Interpreter(modelPath: modelPath)

  // Allocate memory for the model's input `Tensor`s.
  try interpreter.allocateTensors()

  let inputData: Data  // Should be initialized

  // input data preparation...

  // Copy the input data to the input `Tensor`.
  try self.interpreter.copy(inputData, toInputAt: 0)

  // Run inference by invoking the `Interpreter`.
  try self.interpreter.invoke()

  // Get the output `Tensor`
  let outputTensor = try self.interpreter.output(at: 0)

  // Copy output to `Data` to process the inference results.
  let outputSize = outputTensor.shape.dimensions.reduce(1, {x, y in x * y})
  let outputData =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: outputSize)
  outputTensor.data.copyBytes(to: outputData)

  if (error != nil) { /* Error handling... */ }
} catch error {
  // Error handling...
}

Objective-C에서 모델 로드 및 실행

플랫폼: iOS

목표 - C API를 사용할 수 있습니다 TensorFlowLiteObjC Cocoapods에서 포드.

첫째, 당신은 수입에 필요한 TensorFlowLite 모듈.

@import TensorFlowLite;
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];
NSError *error;

// Initialize an interpreter with the model.
TFLInterpreter *interpreter = [[TFLInterpreter alloc] initWithModelPath:modelPath
                                                                  error:&error];
if (error != nil) { /* Error handling... */ }

// Allocate memory for the model's input `TFLTensor`s.
[interpreter allocateTensorsWithError:&error];
if (error != nil) { /* Error handling... */ }

NSMutableData *inputData;  // Should be initialized
// input data preparation...

// Get the input `TFLTensor`
TFLTensor *inputTensor = [interpreter inputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy the input data to the input `TFLTensor`.
[inputTensor copyData:inputData error:&error];
if (error != nil) { /* Error handling... */ }

// Run inference by invoking the `TFLInterpreter`.
[interpreter invokeWithError:&error];
if (error != nil) { /* Error handling... */ }

// Get the output `TFLTensor`
TFLTensor *outputTensor = [interpreter outputTensorAtIndex:0 error:&error];
if (error != nil) { /* Error handling... */ }

// Copy output to `NSData` to process the inference results.
NSData *outputData = [outputTensor dataWithError:&error];
if (error != nil) { /* Error handling... */ }

Objective-C 코드에서 C API 사용

현재 Objective-C API는 대리자를 지원하지 않습니다. 오브젝티브 C 코드를 사용 위임하기 위해 직접 기본 호출 할 필요가 C API를 .

#include "tensorflow/lite/c/c_api.h"
TfLiteModel* model = TfLiteModelCreateFromFile([modelPath UTF8String]);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();

// Create the interpreter.
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

// Allocate tensors and populate the input tensor data.
TfLiteInterpreterAllocateTensors(interpreter);
TfLiteTensor* input_tensor =
    TfLiteInterpreterGetInputTensor(interpreter, 0);
TfLiteTensorCopyFromBuffer(input_tensor, input.data(),
                           input.size() * sizeof(float));

// Execute inference.
TfLiteInterpreterInvoke(interpreter);

// Extract the output tensor data.
const TfLiteTensor* output_tensor =
    TfLiteInterpreterGetOutputTensor(interpreter, 0);
TfLiteTensorCopyToBuffer(output_tensor, output.data(),
                         output.size() * sizeof(float));

// Dispose of the model and interpreter objects.
TfLiteInterpreterDelete(interpreter);
TfLiteInterpreterOptionsDelete(options);
TfLiteModelDelete(model);

C++에서 모델 로드 및 실행

플랫폼: Android, iOS 및 Linux

C ++에서 모델에 저장됩니다 FlatBufferModel 클래스입니다. TensorFlow Lite 모델을 캡슐화하고 모델이 저장된 위치에 따라 몇 가지 다른 방법으로 빌드할 수 있습니다.

class FlatBufferModel {
  // Build a model based on a file. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromFile(
      const char* filename,
      ErrorReporter* error_reporter);

  // Build a model based on a pre-loaded flatbuffer. The caller retains
  // ownership of the buffer and should keep it alive until the returned object
  // is destroyed. Return a nullptr in case of failure.
  static std::unique_ptr<FlatBufferModel> BuildFromBuffer(
      const char* buffer,
      size_t buffer_size,
      ErrorReporter* error_reporter);
};

이제이 같은 모델을 가지고 FlatBufferModel 객체를, 당신은 그것을 실행할 수 있습니다 Interpreter . 하나의 FlatBufferModel 하나 개 이상의에서 동시에 사용할 수 있습니다 Interpreter .

의 중요한 부분 Interpreter 코드에 표시됩니다 API는 다음과 니펫을. 다음 사항에 유의해야 합니다.

  • 텐서는 문자열 비교(및 문자열 라이브러리에 대한 고정 종속성)를 피하기 위해 정수로 표시됩니다.
  • 동시 스레드에서 인터프리터에 액세스하면 안 됩니다.
  • 입출력 텐서의 메모리 할당은 호출 트리거한다 AllocateTensors() 오른쪽 텐서 크기 조정 후.

C++에서 TensorFlow Lite의 가장 간단한 사용법은 다음과 같습니다.

// Load the model
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(filename);

// Build the interpreter
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);

// Resize input tensors, if desired.
interpreter->AllocateTensors();

float* input = interpreter->typed_input_tensor<float>(0);
// Fill `input`.

interpreter->Invoke();

float* output = interpreter->typed_output_tensor<float>(0);

더 많은 예제 코드에 대한 내용 minimal.cclabel_image.cc .

Python에서 모델 로드 및 실행

플랫폼: 리눅스

추론을 실행하기위한 파이썬 API가 제공됩니다 tf.lite 모듈. 어떤에서, 당신은 대부분 만하면 tf.lite.Interpreter 모델을로드하고 추론을 실행합니다.

부하에 파이썬 인터프리터를 사용하는 방법 다음 예제 쇼 .tflite 임의의 입력 데이터 파일 실행 추론 :

이 예는 정의된 SignatureDef를 사용하여 SavedModel에서 변환하는 경우 권장됩니다. TensorFlow 2.5부터 사용 가능

class TestModel(tf.Module):
  def __init__(self):
    super(TestModel, self).__init__()

  @tf.function(input_signature=[tf.TensorSpec(shape=[1, 10], dtype=tf.float32)])
  def add(self, x):
    '''
    Simple method that accepts single input 'x' and returns 'x' + 4.
    '''
    # Name the output 'result' for convenience.
    return {'result' : x + 4}


SAVED_MODEL_PATH = 'content/saved_models/test_variable'
TFLITE_FILE_PATH = 'content/test_variable.tflite'

# Save the model
module = TestModel()
# You can omit the signatures argument and a default signature name will be
# created with name 'serving_default'.
tf.saved_model.save(
    module, SAVED_MODEL_PATH,
    signatures={'my_signature':module.add.get_concrete_function()})

# Convert the model using TFLiteConverter
converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL_PATH)
tflite_model = converter.convert()
with open(TFLITE_FILE_PATH, 'wb') as f:
  f.write(tflite_model)

# Load the TFLite model in TFLite Interpreter
interpreter = tf.lite.Interpreter(TFLITE_FILE_PATH)
# There is only 1 signature defined in the model,
# so it will return it by default.
# If there are multiple signatures then we can pass the name.
my_signature = interpreter.get_signature_runner()

# my_signature is callable with input as arguments.
output = my_signature(x=tf.constant([1.0], shape=(1,10), dtype=tf.float32))
# 'output' is dictionary with all outputs from the inference.
# In this case we have single output 'result'.
print(output['result'])

모델에 SignatureDefs가 정의되어 있지 않은 경우의 또 다른 예입니다.

import numpy as np
import tensorflow as tf

# Load the TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="converted_model.tflite")
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test the model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

미리 변환 된 같은 모델로드의 대안으로 .tflite 파일을, 당신은 당신의 코드를 결합 할 수 있습니다 TensorFlow 라이트 변환기 파이썬 API ( tf.lite.TFLiteConverter 그런 다음 TensorFlow 라이트 형식으로 TensorFlow 모델을 변환 할 수 있도록) 추론 실행:

import numpy as np
import tensorflow as tf

img = tf.placeholder(name="img", dtype=tf.float32, shape=(1, 64, 64, 3))
const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])
val = img + const
out = tf.identity(val, name="out")

# Convert to TF Lite format
with tf.Session() as sess:
  converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out])
  tflite_model = converter.convert()

# Load the TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()

# Continue to get tensors and so forth, as shown above...

더 파이썬 예제 코드을 참조 label_image.py .

팁 : 실행 help(tf.lite.Interpreter) 파이썬 터미널에서 인터프리터에 대한 자세한 문서를 얻을 수 있습니다.

지원되는 작업

TensorFlow Lite는 몇 가지 제한 사항이 있는 TensorFlow 작업의 하위 집합을 지원합니다. 작업 및 제한 사항의 전체 목록을 참조 TF 라이트 옵스 페이지를 .