Помогают защитить Большой Барьерный Риф с TensorFlow на Kaggle Присоединяйтесь вызов

Вывод TensorFlow Lite

Термин умозаключение относится к процессу выполнения модели TensorFlow Lite на устройстве для того , чтобы сделать предсказание , основанное на входных данных. Для того, чтобы выполнить вывод с моделью TensorFlow Lite, вы должны запустить его через переводчика. Интерпретатор TensorFlow Lite разработан, чтобы быть компактным и быстрым. Интерпретатор использует статический порядок графов и настраиваемый (менее динамичный) распределитель памяти для обеспечения минимальной нагрузки, инициализации и задержки выполнения.

Эта страница описывает , как получить доступ к переводчику TensorFlow Lite и выполнить вывод , используя C ++, Java и Python, а также ссылки на другие ресурсы для каждой поддерживаемой платформы .

Важные понятия

Вывод TensorFlow Lite обычно состоит из следующих шагов:

  1. Загрузка модели

    Вы должны загрузить .tflite модели в память, которая содержит график выполнения модели.

  2. Преобразование данных

    Необработанные входные данные для модели обычно не соответствуют формату входных данных, ожидаемому моделью. Например, вам может потребоваться изменить размер изображения или изменить формат изображения, чтобы он был совместим с моделью.

  3. Выполнение вывода

    Этот шаг включает использование TensorFlow Lite API для выполнения модели. Он включает в себя несколько шагов, таких как построение интерпретатора и размещение тензоров, как описано в следующих разделах.

  4. Устный перевод

    Когда вы получаете результаты логического вывода модели, вы должны интерпретировать тензоры осмысленным образом, который будет полезен в вашем приложении.

    Например, модель может возвращать только список вероятностей. Вы должны сопоставить вероятности с соответствующими категориями и представить их конечному пользователю.

Поддерживаемые платформы

API для вывода TensorFlow предназначены для наиболее распространенных мобильных / встраиваемых платформ , таких как Android , прошивка и Linux , на нескольких языках программирования.

В большинстве случаев дизайн API отражает предпочтение производительности, а не простоты использования. TensorFlow Lite разработан для быстрого вывода на небольших устройствах, поэтому неудивительно, что API-интерфейсы пытаются избежать ненужных копий за счет удобства. Точно так же согласованность с API-интерфейсами TensorFlow не была явной целью, и следует ожидать некоторых различий между языками.

Во всех библиотеках API TensorFlow Lite позволяет загружать модели, передавать входные данные и извлекать выходные данные.

Платформа Android

В Android логический вывод TensorFlow Lite может выполняться с использованием API Java или C ++. API-интерфейсы Java обеспечивают удобство и могут использоваться непосредственно в классах Android Activity. API-интерфейсы C ++ предлагают большую гибкость и скорость, но могут потребовать написания оболочек JNI для перемещения данных между уровнями Java и C ++.

Ниже подробно об использовании C ++ и Java , или следовать Android быстрый старт для учебника и примеры кода.

Генератор кода оболочки TensorFlow Lite для Android

Для модели TensorFlow Lite усиливается с метаданными , разработчики могут использовать генератор коды обертки TensorFlow Lite для Android для создания платформы код конкретной обертки. Код обертки устраняет необходимость взаимодействовать непосредственно с ByteBuffer на Android. Вместо этого, разработчики могут взаимодействовать с моделью TensorFlow Lite с типизированными объектами , такими как Bitmap и Rect . Для получения более подробной информации, пожалуйста , обратитесь к генератору коды обертки TensorFlow Lite Android .

Платформа iOS

КСН, TensorFlow Lite поставляется с родной IOS библиотек , написанных на Свифта и Objective-C . Вы можете также использовать C API непосредственно в кодах Objective-C.

Подробности ниже об использовании Swift , Objective-C и C API , или следовать за быстрый старт IOS , для учебника и примеры кода.

Платформа Linux

На платформах Linux ( в том числе Raspberry Pi ), вы можете запустить умозаключения с использованием API - интерфейсов TensorFlow Lite доступны в C ++ и Python , как показано в следующих разделах.

Запуск модели

Запуск модели TensorFlow Lite включает несколько простых шагов:

  1. Загрузите модель в память.
  2. Построение Interpreter на основе существующей модели.
  3. Установите значения входного тензора. (При необходимости измените размер входных тензоров, если предопределенные размеры не требуются.)
  4. Вызвать вывод.
  5. Считайте выходные значения тензора.

В следующих разделах описывается, как эти шаги могут быть выполнены на каждом языке.

Загрузить и запустить модель на Java

Платформа: Android

Java API для запуска умозаключения с TensorFlow Lite в первую очередь предназначен для использования с Android, так это доступно как Android библиотеку зависимости: org.tensorflow:tensorflow-lite .

В Java, вы будете использовать Interpreter класс , чтобы загрузить умозаключение модели и привода модели. Во многих случаях это может быть единственный API, который вам нужен.

Вы можете инициализировать Interpreter с помощью .tflite файла:

public Interpreter(@NotNull File modelFile);

Или с MappedByteBuffer :

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

В обеих случаях необходимо предоставить действительную модель TensorFlow Lite или 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 Lite конвертер при создании модели. Имейте в виду , что порядок тензоров в input должен соответствовать порядку , предоставленный TensorFlow Lite конвертер.

Interpreter класс также предоставляет удобные функции для вас , чтобы получить индекс любой модели ввода или вывода , используя название операции:

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

Если opName не действует операция в модели, он бросает IllegalArgumentException .

Также нужно учитывать , что Interpreter владеет ресурсами. Чтобы избежать утечки памяти, ресурсы должны быть освобождены после использования:

interpreter.close();

Для примера проекта с Java, см образец Android классификации изображений .

Поддерживаемые типы данных (в Java)

Чтобы использовать TensorFlow Lite, типы данных входных и выходных тензоров должны быть одним из следующих примитивных типов:

  • float
  • int
  • long
  • byte

String типы также поддерживаются, но они кодируются иначе , чем примитивные типы. В частности, форма тензора строки определяет количество и расположение строк в тензоре, при этом каждый элемент сам по себе является строкой переменной длины. В этом смысле (байт) размер тензорной не может быть вычислена из формы и типа один, и , следовательно , строки не могут быть предоставлены в виде единого плоского ByteBuffer аргумента.

Если другие типы данных, в том числе в штучной упаковке типов , таких как Integer и Float , используются, IllegalArgumentException будет брошен.

Входы

Каждый вход должен быть массивом или многомерным массивом поддерживаемых типов примитивов, или сырое ByteBuffer соответствующего размера. Если входные данные являются массивом или многомерным массивом, связанный с ним входной тензор будет неявно изменен до размеров массива во время вывода. Если вход является ByteBuffer абонент должен сначала вручную изменить размер связанный с ним тензором ввода (через Interpreter.resizeInput() ) перед запуском умозаключения.

При использовании ByteBuffer , предпочитают использовать прямые буферы байта, так как это позволяет Interpreter , чтобы избежать ненужных копий. Если ByteBuffer является прямым буфер байт, его заказ должен быть ByteOrder.nativeOrder() . После использования для вывода модели он должен оставаться неизменным до завершения вывода модели.

Выходы

Каждый вывод должен быть массивом или многомерным массивом поддерживаемых типов примитивов или ByteBuffer соответствующего размера. Обратите внимание, что у некоторых моделей есть динамические выходы, где форма выходных тензоров может варьироваться в зависимости от входа. Нет простого способа справиться с этим с помощью существующего API вывода Java, но запланированные расширения сделают это возможным.

Загрузите и запустите модель в Swift

Платформа: iOS

Swift API доступен в TensorFlowLiteSwift Pod от 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 Pod из 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... */ }

Использование C API в коде Objective-C

В настоящее время Objective-C API не поддерживает делегатов. Для делегатов использования с кодом Objective-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() сразу после изменения размера тензоров.

Простейшее использование TensorFlow Lite с C ++ выглядит так:

// 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.cc и label_image.cc .

Загрузить и запустить модель в Python

Платформа: Linux

API Python для запуска умозаключение предусмотрен в tf.lite модуле. Из чего, вы в основном нужно только tf.lite.Interpreter загрузить модель и запустить умозаключение.

В следующем примере показано , как использовать интерпретатор Python , чтобы загрузить .tflite файл и запустить умозаключение со случайными входными данными:

Этот пример рекомендуется, если вы конвертируете из SavedModel с определенным SignatureDef. Доступно начиная с 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 файла, вы можете объединить код с API TensorFlow Lite конвертер Python ( tf.lite.TFLiteConverter ), что позволяют превратить вашу модель TensorFlow в формат TensorFlow Lite , а затем выполнить вывод:

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

Для более Python коды образца, см label_image.py .

Совет: Выполнить help(tf.lite.Interpreter) в терминале Python , чтобы получить подробную документацию о переводчике.

Поддерживаемые операции

TensorFlow Lite поддерживает подмножество операций TensorFlow с некоторыми ограничениями. Полный перечень операций и ограничений см страницы TF Lite Ops .