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:
Model yükleme:
.tflite
modelini, şunu içeren belleğe yükleyin: daha da iyileşir.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.
Çı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.
Çı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:
- Model belleğe yükleniyor.
- Mevcut bir modeli temel alan bir
Interpreter
oluşturma. - Giriş tensörü değerlerini ayarlama.
- Çıkarımları çağırma.
- 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()