LiteRT'i kullanmaya başlama

Bu kılavuzda, LiteRT (Lite'ın kısaltması) çalıştırma süreci tanıtılır Çalışma zamanı) giriş verilerine dayalı tahminlerde bulunmak için cihaz üzerinde modeli kullanın. Bu, en az yükleme, başlatma ve yürütme gecikmesi sağlamak için statik bir grafik sıralaması ve özel (daha az dinamik) bir bellek ayırıcı kullanan LiteRT yorumlayıcısı ile elde edilir.

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 ve boyutlara dönüştürün. 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. Çıkarma işlemini çalıştırma: Tahminde bulunmak için LiteRT modelini çalıştırı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. Çıktıyı yorumlama: Çıkış tenörlerini, uygulamanızda yararlı olacak şekilde anlamlı bir şekilde yorumlayın. Örneğin, bir model yalnızca olasılıkların listesini döndürebilir. 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 işlemi Java veya C++ API'leri kullanılarak gerçekleştirilebilir. Java API'leri kolaylık sağlar ve doğrudan Android Activity sınıflarınızda kullanılabilir. C++ API'leri daha fazla esneklik ve hız sunar ancak Java ile C++ katmanları arasında veri taşımak için JNI sarmalayıcıları yazmayı gerektirebilir.

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

iOS Platformu

LiteRT, iOS'te aşağıdaki dillerde mevcuttur: Swift ve Objective-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++.

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. Modeli belleğe yükleme.
  2. Mevcut bir modeli temel alan bir Interpreter oluşturma.
  3. Giriş tenör değerlerini ayarlama.
  4. Çıkarımlar çağırma.
  5. Tensör değerlerini döndürme.

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.

FlatBuffers (.tflite) dosyası kullanarak bir Interpreter başlatabilirsiniz:

public Interpreter(@NotNull File modelFile);

Veya MappedByteBuffer ile:

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

Her iki durumda da geçerli bir LiteRT modeli sağlamanız gerekir. Aksi takdirde API, IllegalArgumentException Bir Interpreter'ü başlatmak için MappedByteBuffer kullanıyorsanız bu değer, Interpreter'ün tüm ömrü boyunca değişmeden kalmalıdır.

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 giriş nesnesine girişler için eşleme.

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

  • İmza Adı (isteğe bağlı): İmza adı (Modelde tek bir imza varsa boş bırakılabilir).

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. Bu nedenle, modelinizde birden fazla giriş veya çıkış varsa bunun yerine şunları kullanın:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

Bu durumda, inputs'teki her giriş bir giriş tenörüne karşılık gelir ve map_of_indices_to_outputs, çıkış tenörlerinin dizinlerini ilgili çıkış verileriyle eşler.

Her iki durumda da, tensör dizinleri verdiğiniz değerlere karşılık gelmelidir. LiteRT Dönüştürücüsü ile otomatik olarak birleştirebilir. input içindeki tensörlerin sırasının, LiteRT Dönüştürücü'ye verilen sırayla eşleşmesi gerektiğini unutmayın.

Interpreter sınıfı, bir işlem adını kullanarak herhangi bir model girişinin veya çıkışının dizini elde etmenize olanak tanıyan kullanışlı işlevler de sağlar:

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

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

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, kullanımdan sonra aşağıdaki yöntemlerle 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 bulabilirsiniz.

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 ilkel türler. Özellikle bir dize tenzorunun şekli, tenzordaki dizelerin sayısını ve düzenini belirler. Her öğe, değişken uzunlukta bir dizedir. Bu bağlamda, tenörün (bayt) boyutu yalnızca şekil ve türden hesaplanamaz ve sonuç olarak dize tek bir düz ByteBuffer bağımsız değişkeni olarak sağlanamaz.

Integer ve Float gibi kutulu türler de dahil olmak üzere başka veri türleri kullanılırsa bir IllegalArgumentException oluşturulur.

Girişler

Her giriş, desteklenen değerlerin dizisi veya çok boyutlu dizisi olmalıdır. temel türler veya uygun boyuttaki ham ByteBuffer değerler olabilir. Giriş bir dizi veya çok boyutlu diziyse ilişkili giriş tensörü, çıkarım sırasında dizi boyutlarına göre dolaylı olarak yeniden boyutlandırılır. Giriş bir ByteBuffer ise çağıran, çıkarım yapmadan önce ilişkili giriş tenörünü manuel olarak yeniden boyutlandırmalıdır (Interpreter.resizeInput() aracılığıyla).

ByteBuffer kullanırken, doğrudan bayt arabelleklerini kullanmayı tercih edin. Bu, Gereksiz kopyaları önlemek için Interpreter. ByteBuffer doğrudan bir bayt arabelleğiyse sırası ByteOrder.nativeOrder() olmalıdır. Model çıkarım işlemi için kullanıldıktan sonra, model çıkarım işlemi 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 Java çıkarım API'si ile bunu yapmanın doğrudan bir yolu yoktur ancak planlanan uzantılar bunu mümkün kılacaktır.

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, temsilcileri 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 FlatBufferModel sınıfında depolanır. 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);
};

Modeli FlatBufferModel nesnesi olarak oluşturduğunuza göre Interpreter ile yürütebilirsiniz. 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:

  • Dize karşılaştırmalarını (ve dize kitaplıklarına sabit bağımlılıkları) önlemek için tenzorlar tam sayılarla temsil edilir.
  • Çevirmene eşzamanlı iş parçalarından 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 minimal.cc ve label_image.cc bölümüne bakın.

Python

Tahmin yürütmek için kullanılan Python API, bir model yüklemek ve tahmin yürütmek için Interpreter kullanı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, FlatBuffers (.tflite) dosyası yüklemek ve rastgele giriş verileriyle çıkarım çalıştırmak için Python yorumlayıcısının nasıl kullanılacağı gösterilmektedir:

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üklemek yerine, kodunuzu LiteRT Compiler ile birleştirebilirsiniz. Böylece, Keras modelinizi LiteRT biçimine dönüştürebilir ve ardından çıkarım çalıştırabilirsiniz:

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 bölümüne bakın.

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 . 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ımlandığı ve [3, 10] olarak yeniden boyutlandırılması gerektiği varsayılır.

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