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:
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 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.
Çı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.
Çı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:
- Modeli belleğe yükleme.
- Mevcut bir modeli temel alan bir
Interpreter
oluşturma. - Giriş tenör değerlerini ayarlama.
- Çıkarımlar çağırma.
- 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()