Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

TensorFlow Lite çıkarımı

Çıkarım terimi, girdi verilerine dayalı tahminler yapmak için TensorFlow Lite modelini cihazda yürütme sürecini ifade eder. TensorFlow Lite modeliyle bir çıkarım gerçekleştirmek için, bunu bir yorumlayıcı aracılığıyla çalıştırmanız gerekir. TensorFlow Lite yorumlayıcı, yalın ve hızlı olacak şekilde tasarlanmıştır. Yorumlayıcı, minimum 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ı kullanır.

Bu sayfa, TensorFlow Lite yorumlayıcısına nasıl erişileceğini ve C ++, Java ve Python kullanarak bir çıkarım yapmanın yanı sıra desteklenen her platform için diğer kaynaklara bağlantıları açıklar.

Önemli kavramlar

TensorFlow Lite çıkarımı tipik olarak aşağıdaki adımları izler:

  1. Bir model yükleme

    .tflite modelini, modelin yürütme grafiğini içeren belleğe yüklemeniz gerekir.

  2. Verileri dönüştürme

    Model için ham girdi verileri genellikle modelin beklediği girdi veri formatıyla eşleşmez. Örneğin, modelle uyumlu olması için bir görüntüyü yeniden boyutlandırmanız veya görüntü formatını değiştirmeniz gerekebilir.

  3. Çıkarım çalıştırma

    Bu adım, modeli yürütmek için TensorFlow Lite API'nin kullanılmasını içerir. Aşağıdaki bölümlerde açıklandığı gibi, yorumlayıcı oluşturma ve tensörleri tahsis etme gibi birkaç adımı içerir.

  4. Çıktıyı yorumlama

    Model çıkarımından sonuçlar aldığınızda, tensörleri, uygulamanızda faydalı olacak anlamlı bir şekilde yorumlamalısınız.

    Örneğin, bir model yalnızca bir olasılık listesi döndürebilir. Olasılıkları ilgili kategorilerle eşlemek ve son kullanıcınıza sunmak size kalmıştır.

Desteklenen platformlar

TensorFlow çıkarım API'leri, Android, iOS ve Linux gibi en yaygın mobil / gömülü platformlar için birden çok programlama dilinde sağlanır.

Çoğu durumda, API tasarımı, kullanım kolaylığı yerine performans tercihini yansıtır. TensorFlow Lite, küçük cihazlarda hızlı çıkarım için tasarlanmıştır, bu nedenle API'lerin kolaylık pahasına gereksiz kopyalardan kaçınmaya çalışması şaşırtıcı olmamalıdır. Benzer şekilde, TensorFlow API'leriyle tutarlılık açık bir hedef değildi ve diller arasında bazı farklılıklar olması bekleniyordu.

Tüm kitaplıklarda TensorFlow Lite API, modelleri yüklemenizi, girişleri beslemenizi ve çıkarım çıktılarını almanızı sağlar.

Desteklenen işlemler

TensorFlow Lite, bazı sınırlamalarla TensorFlow işlemlerinin bir alt kümesini destekler. İşlemlerin ve sınırlamaların tam listesi için TF Lite Ops sayfasına bakın .

Android

Android'de TensorFlow Lite çıkarımı, Java veya C ++ API'leri kullanılarak gerçekleştirilebilir. Java API'leri kolaylık sağlar ve doğrudan Android Aktivite sınıflarınız içinde kullanılabilir. C ++ API'leri daha fazla esneklik ve hız sunar, ancak verileri Java ve C ++ katmanları arasında taşımak için JNI sarmalayıcılar yazmayı gerektirebilir.

C ++ ve Java kullanımıyla ilgili ayrıntılar için aşağıya bakın veya bir eğitim ve örnek kod için Android hızlı başlangıcını izleyin.

TensorFlow Lite Android sarmalayıcı kod üreteci

Meta verilerle geliştirilmiş TensorFlow Lite modeli için geliştiriciler, platforma özgü sarmalayıcı kodu oluşturmak için TensorFlow Lite Android sarmalayıcı kod oluşturucuyu kullanabilir. Sarmalayıcı kodu, Android'de doğrudan ByteBuffer ile etkileşim ByteBuffer ihtiyacını ortadan kaldırır. Bunun yerine, geliştiriciler TensorFlow Lite modeliyle Bitmap ve Rect gibi yazılı nesnelerle etkileşime girebilirler. Daha fazla bilgi için lütfen TensorFlow Lite Android sarıcı kod oluşturucuya bakın.

iOS

İOS'ta TensorFlow Lite, Swift ve Objective-C ile yazılmış yerel iOS kitaplıklarıyla kullanılabilir. C API'yi doğrudan Objective-C kodlarında da kullanabilirsiniz.

Swift, Objective-C ve C API kullanımıyla ilgili ayrıntılar için aşağıya bakın veya bir eğitim ve örnek kod için iOS hızlı başlangıcını izleyin.

Linux

Linux platformlarında ( Raspberry Pi dahil), aşağıdaki bölümlerde gösterildiği gibi, C ++ ve Python'da bulunan TensorFlow Lite API'lerini kullanarak çıkarımlar çalıştırabilirsiniz.

Bir model çalıştırma

Bir TensorFlow Lite modelini çalıştırmak birkaç basit adımı içerir:

  1. Modeli belleğe yükleyin.
  2. Mevcut bir modeli temel alan bir Interpreter oluşturun.
  3. Giriş tensör değerlerini ayarlayın. (Önceden tanımlanmış boyutlar istenmiyorsa isteğe bağlı olarak giriş tensörlerini yeniden boyutlandırın.)
  4. Çıkarımı çağırın.
  5. Çıkış tensör değerlerini okuyun.

Aşağıdaki bölümler, bu adımların her dilde nasıl yapılabileceğini açıklamaktadır.

Java'da bir model yükleme ve çalıştırma

Platform: Android

TensorFlow Lite ile bir çıkarım çalıştırmak için Java API, öncelikle Android ile kullanılmak üzere tasarlanmıştır, bu nedenle bir Android kitaplık bağımlılığı olarak mevcuttur: org.tensorflow:tensorflow-lite .

Java'da, bir model yüklemek ve model çıkarımı yapmak için Interpreter sınıfını kullanacaksınız. Çoğu durumda, ihtiyacınız olan tek API bu olabilir.

Bir sunabilmesi Interpreter bir kullanarak .tflite dosyası:

public Interpreter(@NotNull File modelFile);

Veya MappedByteBuffer :

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

Her iki durumda da, geçerli bir TensorFlow Lite modeli sağlaması gerekir veya API atar IllegalArgumentException . Bir Interpreter başlatmak için MappedByteBuffer kullanırsanız, Interpreter tüm ömrü boyunca değişmeden kalması gerekir.

Daha sonra modelle bir çıkarım yapmak için, Interpreter.run() çağırmanız yeterlidir. Örneğin:

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

run() yöntemi yalnızca bir girdi alır ve yalnızca bir çıktı döndürür. Dolayısıyla, modelinizin birden çok girişi veya birden çok çıkışı varsa, bunun yerine şunu kullanın:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

Bu durumda, inputs her girdi bir girdi tensörüne karşılık gelir ve map_of_indices_to_outputs , çıktı tensörlerinin indislerini karşılık gelen çıktı verilerine eşler.

Her iki durumda da, tensör endeksleri, modeli oluştururken TensorFlow Lite Converter'a verdiğiniz değerlere karşılık gelmelidir. İçinde Tensörlerin sırası unutmayın input TensorFlow Lite Converter verilen emri aynı olmalıdır.

Interpreter sınıfı, bir işlem adı kullanarak herhangi bir model girdisinin veya çıktısının dizinini almanız için kullanışlı işlevler de sağlar:

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

Eğer opName modelinde geçerli bir işlem değildir, bir atar IllegalArgumentException .

Ayrıca, Interpreter kaynaklara sahip olduğuna dikkat edin. Bellek sızıntısını önlemek için, kaynaklar kullanımdan sonra aşağıdakiler tarafından serbest bırakılmalıdır:

interpreter.close();

Java ile örnek bir proje için Android görüntü sınıflandırma örneğine bakın .

Desteklenen veri türleri (Java'da)

TensorFlow Lite'ı kullanmak için, giriş ve çıkış tensörlerinin veri türleri aşağıdaki ilkel türlerden biri olmalıdır:

  • float
  • int
  • long
  • byte

String türleri de desteklenir, ancak ilkel türlerden farklı şekilde kodlanırlar. Özellikle, bir dizi Tensörünün şekli, Tensördeki dizelerin sayısını ve düzenlemesini belirler, her bir elemanın kendisi değişken uzunluklu bir dizedir. Bu anlamda, Tensörün (bayt) boyutu yalnızca şekil ve türden hesaplanamaz ve sonuç olarak dizeler tek, düz bir ByteBuffer argümanı olarak sağlanamaz.

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

Girişler

Her girdi, desteklenen ilkel türlerin bir dizisi veya çok boyutlu dizisi veya uygun boyutta bir ham ByteBuffer . Girdi bir dizi veya çok boyutlu bir diziyse, ilişkili girdi tensörü, çıkarım zamanında örtük olarak dizinin boyutlarına göre yeniden boyutlandırılacaktır. Giriş bir ByteBuffer ise, arayanın çıkarımı çalıştırmadan önce ilgili giriş tensörünü ( Interpreter.resizeInput() aracılığıyla Interpreter.resizeInput() manuel olarak yeniden boyutlandırması gerekir.

ByteBuffer kullanırken, Interpreter gereksiz kopyalardan kaçınmasına olanak tanıdığından, doğrudan bayt arabelleklerini kullanmayı tercih edin. ByteBuffer bir doğrudan bayt arabelleğiyse, sırası ByteOrder.nativeOrder() olmalıdır. Bir model çıkarımı için kullanıldıktan sonra, model çıkarımı bitene kadar değişmeden kalmalıdır.

çıktılar

Her çıktı, desteklenen ilkel türlerin bir dizisi veya çok boyutlu dizisi veya uygun boyutta bir ByteBuffer olmalıdır. Bazı modellerin, çıkış tensörlerinin şeklinin girdiye bağlı olarak değişebileceği dinamik çıktılara sahip olduğuna dikkat edin. Mevcut Java çıkarım API'si ile bunu halletmenin basit bir yolu yoktur, ancak planlanan uzantılar bunu mümkün kılacaktır.

Swift'de bir model yükleyin ve çalıştırın

Platform: iOS

Swift API , TensorFlowLiteSwift Pod'da mevcuttur.

Öncelikle, TensorFlowLite modülünü içe TensorFlowLite 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...
}

Objective-C'de bir model yükleyin ve çalıştırın

Platform: iOS

Objective-C API , TensorFlowLiteObjC Pod'da mevcuttur.

Öncelikle, TensorFlowLite modülünü içe TensorFlowLite 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...

// Copy the input data to the input `TFLTensor`.
[interpreter copyData:inputData toInputTensorAtIndex:0 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:&amp;error];
if (error != nil) { /* Error handling... */ }

Objective-C kodunda C API kullanma

Şu anda Objective-C API delegeleri desteklemiyor. Temsilcileri Objective-C koduyla kullanmak için, doğrudan temel C API'yi çağırmanız gerekir.

#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 ++ 'da bir model yükleme ve çalıştırma

Platformlar: Android, iOS ve Linux

C ++ 'da, model FlatBufferModel sınıfında saklanır. Bir TensorFlow Lite modelini kapsüller ve modelin nerede depolandığına bağlı olarak birkaç farklı şekilde oluşturabilirsiniz:

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

Artık modeli bir FlatBufferModel nesnesi olarak elde ettiğinize göre, onu bir Interpreter ile çalıştırabilirsiniz. Tek bir FlatBufferModel , birden fazla Interpreter tarafından aynı anda kullanılabilir.

Interpreter API'nin önemli bölümleri aşağıdaki kod parçacığında gösterilmektedir. Bu not alınmalı:

  • Tensörler, dize karşılaştırmalarından (ve dize kitaplıklarına herhangi bir sabit bağımlılıktan) kaçınmak için tamsayılarla temsil edilir.
  • Bir yorumlayıcıya eşzamanlı evrelerden erişilmemelidir.
  • Giriş ve çıkış tensörleri için bellek tahsisi, tensörleri yeniden boyutlandırdıktan hemen sonra AllocateTensors() çağrılarak tetiklenmelidir.

TensorFlow Lite'ın C ++ ile en basit kullanımı şuna benzer:

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

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

Python'da bir model yükleme ve çalıştırma

Platform: Linux

Bir çıkarım çalıştırmak için Python API tf.lite modülünde sağlanır. Bundan, bir modeli yüklemek ve bir çıkarım çalıştırmak için çoğunlukla yalnızca tf.lite.Interpreter ihtiyacınız vardır.

Aşağıdaki örnek, bir .tflite dosyasını yüklemek ve rastgele girdi verileriyle çıkarım çalıştırmak için Python yorumlayıcısının nasıl kullanılacağını gösterir:

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)

Modeli önceden dönüştürülmüş bir .tflite dosyası olarak yüklemeye alternatif olarak, kodunuzu TensorFlow Lite Converter Python API ( tf.lite.TFLiteConverter ) ile birleştirerek TensorFlow modelinizi TensorFlow Lite formatına ve ardından çıkarım yapmak:

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

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

İpucu: Yorumlayıcı hakkında ayrıntılı belgeler almak için Python terminalinde help(tf.lite.Interpreter) çalıştırın.

Özel bir operatör yazın

Tüm TensorFlow Lite operatörleri (hem özel hem de yerleşik), dört işlevden oluşan basit bir saf-C arayüzü kullanılarak tanımlanır:

typedef struct {
  void* (*init)(TfLiteContext* context, const char* buffer, size_t length);
  void (*free)(TfLiteContext* context, void* buffer);
  TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node);
  TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node);
} TfLiteRegistration;

TfLiteContext ve TfLiteNode ilgili ayrıntılar için context.h bakın. İlki, hata raporlama olanakları ve tüm tensörler dahil olmak üzere küresel nesnelere erişim sağlar. İkincisi, uygulamaların kendi giriş ve çıkışlarına erişmesine izin verir.

Yorumlayıcı bir model yüklediğinde, grafikteki her düğüm için bir kez init() çağırır. init() grafikte birden çok kez kullanılırsa, verilen bir init() birden fazla çağrılacaktır. Özel operasyonlar için, parametre adlarını değerlerine eşleyen bir flexbuffer içeren bir konfigürasyon tamponu sağlanacaktır. Yerleşik işlemler için arabellek boştur çünkü yorumlayıcı işlem parametrelerini zaten ayrıştırmıştır. Durum gerektiren çekirdek uygulamaları onu burada başlatmalı ve sahipliği arayana aktarmalıdır. Her init() çağrısı için, uygulamaların init() de tahsis etmiş olabilecekleri tamponu elden çıkarmasına izin veren karşılık gelen bir free() çağrısı olacaktır.

Girdi tensörleri yeniden boyutlandırıldığında, yorumlayıcı, değişikliğin uygulamalarını bildiren grafikten geçecektir. Bu onlara dahili tamponlarını yeniden boyutlandırma, giriş şekillerinin ve türlerinin geçerliliğini kontrol etme ve çıktı şekillerini yeniden hesaplama şansı verir. Bu, tüm prepare() aracılığıyla yapılır ve uygulamalar, durumlarına node->user_data kullanarak node->user_data .

Son olarak, çıkarım her çalıştığında, yorumlayıcı invoke() çağıran grafiğin üzerinden geçer ve burada da durum node->user_data olarak mevcuttur.

Özel operasyonlar, bu dört işlevi tanımlayarak ve genellikle aşağıdaki gibi görünen genel bir kayıt işlevi tanımlayarak yerleşik operasyonlarla tamamen aynı şekilde uygulanabilir:

namespace tflite {
namespace ops {
namespace custom {
  TfLiteRegistration* Register_MY_CUSTOM_OP() {
    static TfLiteRegistration r = {my_custom_op::Init,
                                   my_custom_op::Free,
                                   my_custom_op::Prepare,
                                   my_custom_op::Eval};
    return &r;
  }
}  // namespace custom
}  // namespace ops
}  // namespace tflite

Kaydın otomatik olmadığını ve bir yerde Register_MY_CUSTOM_OP açık bir çağrı yapılması gerektiğini unutmayın. Standart BuiltinOpResolver ( :builtin_ops hedefinden :builtin_ops ) yerleşiklerin kaydını üstlenirken, özel işlemlerin ayrı özel kitaplıklarda toplanması gerekecektir.

Çekirdek kitaplığını özelleştirin

Arka planda yorumlayıcı, modeldeki her bir operatörü çalıştırmak için atanacak bir çekirdek kitaplığı yükleyecektir. Varsayılan kitaplık yalnızca yerleşik çekirdekler içermekle birlikte, onu özel bir kitaplıkla değiştirmek mümkündür.

Yorumlayıcı, operatör kodlarını ve adlarını gerçek koda çevirmek için bir OpResolver kullanır:

class OpResolver {
  virtual TfLiteRegistration* FindOp(tflite::BuiltinOperator op) const = 0;
  virtual TfLiteRegistration* FindOp(const char* op) const = 0;
  virtual void AddOp(tflite::BuiltinOperator op, TfLiteRegistration* registration) = 0;
  virtual void AddOp(const char* op, TfLiteRegistration* registration) = 0;
};

Düzenli kullanım, BuiltinOpResolver kullanmanızı ve şunu BuiltinOpResolver gerektirir:

tflite::ops::builtin::BuiltinOpResolver resolver;

İsteğe bağlı olarak özel operasyonları kaydedebilirsiniz (çözücüyü InterpreterBuilder iletmeden önce):

resolver.AddOp("MY_CUSTOM_OP", Register_MY_CUSTOM_OP());

OpResolver çok büyük olduğu kabul OpResolver , yeni bir OpResolver , belirli bir işlem alt kümesine, muhtemelen yalnızca belirli bir modelde bulunanlara dayalı olarak kod üretilebilir. Bu, TensorFlow'un seçici kaydının eşdeğeridir (ve basit bir sürümü tools dizininde mevcuttur).