LiteRT'i kullanmaya başlama

Bu kılavuzda, aşağıdakileri yapmak için cihazda LiteRT modeli çalıştırma işlemi tanıtılmaktadır: giriş verilerine dayalı tahminlerde bulunun. Bu, LiteRT ile gerçekleştirilir özel (daha az dinamik) bir özel (daha az dinamik) minimum yük, başlatma ve yürütme gecikmesi sağlamak için bellek ayırıcı.

LiteRT çıkarımı genellikle aşağıdaki adımları izler:

  1. Model yükleme: .tflite modelini, şunu içeren belleğe yükleyin: daha da iyileşir.

  2. Verileri dönüştürme: Giriş verilerini beklenen biçime dönüştürün ve seçin. Modelin ham giriş verileri genellikle girişle eşleşmiyor veri biçiminin kullanılması beklenmektedir. Örneğin, bir aracı yeniden boyutlandırmak için resmi modelle uyumlu olacak şekilde değiştirin veya resim biçimini değiştirin.

  3. Çıkarım çalıştırma: Tahminde bulunmak için LiteRT modelini yürütün. Bu adım, modeli yürütmek için LiteRT API'yi kullanmayı içerir. Bunun için birkaç çeviriciyi inşa etmek ve tensör atamak gibi.

  4. Çıkışı yorumlama: Çıkış tensörlerini anlamlı bir şekilde yorumlayın bulunacaktır. Örneğin, bir model yalnızca olasılık listesidir. Olasılıkları alakalı dönemlerle eşlemek size ve çıktıyı biçimlendirin.

Bu kılavuzda, LiteRT çevirmeninine nasıl erişeceğiniz ve çıkarım yapmak için kullanılır.

Desteklenen platformlar

TensorFlow çıkarım API'leri en yaygın mobil cihazlar ve yerleşik cihazlar için sağlanır Android, iOS ve Linux gibi platformlarda birden fazla programlama dili kullanın.

Çoğu durumda API tasarımı, 2004'e kadar kullanım kolaylığı yerine performans pek de iyi olmadığını unutmayın. LiteRT, küçük cihazlarda hızlı çıkarım için tasarlanmıştır. Bu nedenle API'ler, gereksiz kopyalar bırakır.

LiteRT API, tüm kitaplıklarda modelleri, feed girişlerini ve çıkarım çıktılarını alma.

Android Platformu

Android'de, LiteRT çıkarımı, Java veya C++ API'leri kullanılarak yapılabilir. İlgili içeriği oluşturmak için kullanılan Java API'leri kolaylık sağlar ve doğrudan Android cihazınızda kullanılabilir. Etkinlik dersleri. C++ API'leri daha fazla esneklik ve hız sunar, ancak Java ve C++ katmanları arasında veri taşımak için JNI sarmalayıcıları yazma.

Daha fazla bilgi için C++ ve Java bölümlerini inceleyin veya Android hızlı başlangıç kılavuzunu takip edin.

iOS Platformu

LiteRT, iOS'te aşağıdaki dillerde mevcuttur: Swift ve Hedef-C iOS kitaplıkları. Ayrıca C API Objective-C koduna ekleyebilirsiniz.

Swift, Objective-C ve C API'yi inceleyin bölümlerini veya iOS hızlı başlangıç kılavuzunu takip edin.

Linux Platformu

Linux platformlarında, şurada bulunan LiteRT API'lerini kullanarak çıkarımlar çalıştırabilirsiniz: C++ tuşlarına basın.

Model yükleme ve çalıştırma

LiteRT modeli yükleme ve çalıştırma işlemleri aşağıdaki adımları içerir:

  1. Model belleğe yükleniyor.
  2. Mevcut bir modeli temel alan bir Interpreter oluşturma.
  3. Giriş tensörü değerlerini ayarlama.
  4. Çıkarımları çağırma.
  5. Tensör değerlerinin çıkışı.

Android (Java)

LiteRT ile çıkarımlar çalıştırmaya yönelik Java API, özellikle Android ile çalışır; dolayısıyla bir Android kitaplığı bağımlılığı olarak kullanılabilir: com.google.ai.edge.litert

Java'da Interpreter sınıfını kullanarak bir model yükleyin ve modeli kullanın çıkarım. Çoğu durumda, ihtiyacınız olan tek API bu olabilir.

Bir Interpreter öğesini FlatBuffers (.tflite) dosyası kullanarak başlatabilirsiniz:

public Interpreter(@NotNull File modelFile);

Alternatif olarak, MappedByteBuffer ile:

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

Her iki durumda da geçerli bir LiteRT modeli sağlamanız gerekir. Aksi takdirde API, IllegalArgumentException BirMappedByteBuffer Interpreter, ömrü boyunca değişmeden kalmalıdır. Interpreter.

Bir model üzerinde çıkarım yapmanın tercih edilen yolu imza kullanmaktır. Tensorflow 2.5 sürümünden itibaren dönüştürülen modeller için

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 yöntemi üç bağımsız değişken alır:

  • Girişler : İmzadaki giriş adından bir girişe yapılan girişleri eşler nesnesini tanımlayın.

  • Çıkışlar : İmzadaki çıkış adından çıkışa çıkış eşlemesi verileri.

  • İmza Adı (isteğe bağlı): İmza adı ( tek imzaya sahip olması gerekir).

Modelin tanımlanmış bir imzası olmadığında çıkarımları çalıştırmanın diğer bir yolu. Interpreter.run() numaralı telefonu aramanız yeterli. Örneğin:

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

run() yöntemi yalnızca bir giriş alır ve yalnızca bir çıkış döndürür. Dolayısıyla modelin birden fazla girişi veya çıkışı var. Bunun yerine şunu kullanın:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

Bu durumda, inputs içindeki her giriş bir giriş tensörüne karşılık gelir ve map_of_indices_to_outputs, çıkış tensörleri dizinlerini karşılık gelen değerlerle eşler çıkış verileri.

Her iki durumda da tensör indeksleri, verdiğiniz değerlere karşılık gelmelidir. LiteRT Dönüştürücüsü ile otomatik olarak birleştirebilir. Dikkatli olun input bölgesindeki tensörlerin sırası, LiteRT'te verilen sırayla eşleşmelidir Dönüştürücü.

Interpreter sınıfı, aşağıdakileri elde etmeniz için kullanışlı işlevler de sağlar: işlem adı kullanan herhangi bir model girişinin veya çıkışının dizini:

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

opName, modelde geçerli bir işlem değilse bir IllegalArgumentException.

Ayrıca kaynakların Interpreter adlı kullanıcıya ait olduğunu da unutmayın. Bellek sızıntısını önlemek için kaynaklar, aşağıdakilerin kullanımından sonra serbest bırakılmalıdır:

interpreter.close();

Java ile örnek bir proje için Android nesne algılama örneğine bakın uygulamasında gösterilir.

Desteklenen veri türleri

LiteRT'yi kullanmak için giriş ve çıkış tensörlerinin veri türleri şu temel türler:

  • float
  • int
  • long
  • byte

String türleri de desteklenir ancak bu türler temel türler. Özellikle, bir dizenin şekli Tensor'un sayısını belirler. ve dizelerin Tensor'da düzenlenmesi ve her bir öğenin kendisi bir değişken uzunluklu dize. Bu anlamda, Tensor'ın (bayt) boyutu tek başına şekilden ve türden hesaplanmıştır, dolayısıyla dizeler tek ve düz bir ByteBuffer bağımsız değişkeni olarak sağlanır.

Integer ve Float gibi kutulu türler de dahil olmak üzere diğer veri türleri kullanılırsa IllegalArgumentException atılacak.

Girişler

Her giriş, desteklenen değerlerin dizisi veya çok boyutlu dizisi olmalıdır. temel türler veya uygun boyuttaki ham ByteBuffer değerleridir. Giriş çok boyutlu bir diziyse, ilişkili giriş tensörü çıkarım sırasında dizinin boyutlarına göre dolaylı olarak yeniden boyutlandırılır. Giriş çağrı yapan kullanıcının önce ilişkili girişi manuel olarak yeniden boyutlandırması gerekir. tensor (Interpreter.resizeInput() üzerinden) iletir.

ByteBuffer kullanırken, doğrudan bayt arabelleklerini kullanmayı tercih edin. Bu, Gereksiz kopyaları önlemek için Interpreter. ByteBuffer doğrudan bir baytsa arabellekte, sırası ByteOrder.nativeOrder() olmalıdır. Bir süre kullanıldıktan sonra bu çıkarım, model çıkarımı tamamlanana kadar değişmeden kalmalıdır.

Çıkışlar

Her çıkış, desteklenen verilerin dizisi veya çok boyutlu dizisi olmalıdır. temel türleri veya uygun boyutta bir ByteBuffer Bazı modellerin çıkış tensörlerinin şekli bağlı olarak değişebilen dinamik çıkışlara sahiptir. girdi. Mevcut müşteri planıyla bunu ele almanın kolay bir yolu yoktur. Ancak planlanmış uzantılar bunu mümkün kılar.

iOS (Swift)

Swift API Cocoapods'un TensorFlowLiteSwift Kapsülünde mevcut.

Öncelikle TensorFlowLite modülünü içe aktarmanız gerekir.

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

iOS (Hedef-C)

Hedef-C API Cocoapods'un LiteRTObjC Kapsülünde mevcut.

Öncelikle TensorFlowLiteObjC modülünü içe aktarmanız gerekir.

@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 kodunda C API

Objective-C API, yetki verilmiş kullanıcıları desteklemez. Yetki verilmiş kullanıcıları Objective-C kodu varsa doğrudan temel C'yi çağırmanız gerekir. 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++

LiteRT ile çıkarım çalıştırmak için kullanılan C++ API; Android, iOS, ve Linux platformlarında. iOS'te C++ API yalnızca bazel kullanılırken kullanılabilir.

C++'ta model şurada depolanır: FlatBufferModel sınıfı. Bu bir LiteRT modeli içerir ve bunu birkaç farklı yöntemlerinden birini seçin:

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

Modelinizi artık FlatBufferModel nesnesi olarak oluşturduğunuza göre yürütebilirsiniz şununla: Interpreter Tek bir FlatBufferModel, birden fazla kullanıcı tarafından aynı anda kullanılabilir Interpreter.

Interpreter API'nin önemli bölümleri kod snippet'inde gösterilmiştir bölümüne göz atın. Aşağıdaki noktalara dikkat edilmelidir:

  • Tensörler, dize karşılaştırmalarını önlemek için tam sayılarla temsil edilir (ve dize kitaplıklarındaki sabit bağımlılıklar)
  • Eşzamanlı iş parçacıklarından çevirmene erişilmemelidir.
  • Giriş ve çıkış tensörleri için bellek ayırma, Tensörler yeniden boyutlandırıldıktan hemen sonra AllocateTensors().

LiteRT'in C++ ile en basit kullanımı şu şekilde görünür:

// 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 needed.
interpreter->AllocateTensors();

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

interpreter->Invoke();

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

Daha fazla örnek kod için bkz. minimal.cc ve label_image.cc.

Python

Çıkarımları çalıştırmak için Python API, Interpreter: Bir modeli yüklemek ve bir yöntem de vardır.

LiteRT paketini yükleyin:

$ python3 -m pip install ai-edge-litert

LiteRT Çevirmenini İçe Aktarma

from ai_edge_litert.interpreter import Interpreter
Interpreter = Interpreter(model_path=args.model.file)

Aşağıdaki örnekte, bir FlatBuffers (.tflite) dosyası oluşturabilir ve rastgele giriş verileriyle çıkarım yapabilirsiniz:

Bu örnek, SavedModel'den tanımlı bir İmzalandı.

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 LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = 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'])

Modelde SignatureDefs tanımlanmamışsa başka bir örnek.

import numpy as np
import tensorflow as tf

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(TFLITE_FILE_PATH)
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)

Modeli önceden dönüştürülmüş bir .tflite dosyası olarak yüklemeye alternatif olarak, kodunuzu LiteRT ile Derleyici kullanarak Keras modelinizi LiteRT biçimine dönüştürebilir ve daha sonra, çıkarım:

import numpy as np
import tensorflow as tf

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

# Convert to LiteRT format
converter = tf.lite.TFLiteConverter.from_keras_model(tf.keras.models.Model(inputs=[img], outputs=[out]))
tflite_model = converter.convert()

# Load the LiteRT model and allocate tensors.
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_content=tflite_model)
interpreter.allocate_tensors()

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

Daha fazla Python örnek kodu için label_image.py.

Dinamik şekil modeliyle çıkarım çalıştırma

Dinamik giriş şekline sahip bir model çalıştırmak istiyorsanız giriş şeklini yeniden boyutlandırın çıkarmanız gerekir. Aksi takdirde, Tensorflow modellerindeki None şekli LiteRT modellerinde 1 yer tutucusuyla değiştirilir.

Aşağıdaki örneklerde, giriş şeklini çalıştırmadan önce nasıl yeniden boyutlandıracağınız gösterilmektedir çıkarımları yapabilirsiniz. Tüm örneklerde, giriş şeklinin [1/None, 10] olarak tanımlanıyor ve [3, 10] olarak yeniden boyutlandırılması gerekiyor.

C++ örneği:

// Resize input tensors before allocate tensors
interpreter->ResizeInputTensor(/*tensor_index=*/0, std::vector<int>{3,10});
interpreter->AllocateTensors();

Python örneği:

# Load the LiteRT model in LiteRT Interpreter
from ai_edge_litert.interpreter import Interpreter
interpreter = Interpreter(model_path=TFLITE_FILE_PATH)

# Resize input shape for dynamic shape model and allocate tensor
interpreter.resize_tensor_input(interpreter.get_input_details()[0]['index'], [3, 10])
interpreter.allocate_tensors()

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