مؤتمر Google I / O هو التفاف! تابع جلسات TensorFlow اعرض الجلسات

استنتاج TensorFlow Lite

ويشير الاستدلال المدى لعملية تنفيذ نموذج TensorFlow لايت على الجهاز من أجل جعل التوقعات استنادا إلى بيانات الإدخال. لإجراء الاستدلال مع نموذج TensorFlow لايت، يجب تشغيله من خلال مترجم. تم تصميم مترجم TensorFlow Lite ليكون خفيفًا وسريعًا. يستخدم المترجم الفوري ترتيبًا بيانيًا ثابتًا ومخصص ذاكرة مخصصًا (أقل ديناميكية) لضمان الحد الأدنى من التحميل والتهيئة وزمن انتقال التنفيذ.

توضح هذه الصفحة كيفية الوصول إلى مترجم TensorFlow ايت وأداء الاستنتاج باستخدام C ++، جافا، وبيثون، بالاضافة الى وصلات إلى الموارد الأخرى لكل منصة دعم .

مفاهيم مهمة

عادةً ما يتبع استنتاج TensorFlow Lite الخطوات التالية:

  1. تحميل نموذج

    يجب تحميل .tflite النموذج في الذاكرة، والذي يحتوي على الرسم البياني تنفيذ النموذج.

  2. تحويل البيانات

    لا تتطابق بيانات الإدخال الأولية للنموذج بشكل عام مع تنسيق بيانات الإدخال الذي يتوقعه النموذج. على سبيل المثال ، قد تحتاج إلى تغيير حجم صورة أو تغيير تنسيق الصورة لتتوافق مع النموذج.

  3. تشغيل الاستدلال

    تتضمن هذه الخطوة استخدام TensorFlow Lite API لتنفيذ النموذج. يتضمن خطوات قليلة مثل بناء المترجم الفوري ، وتخصيص الموترات ، كما هو موضح في الأقسام التالية.

  4. تفسير الإخراج

    عندما تتلقى نتائج من الاستدلال النموذجي ، يجب عليك تفسير الموترات بطريقة مفيدة مفيدة في تطبيقك.

    على سبيل المثال ، قد يعرض النموذج قائمة بالاحتمالات فقط. الأمر متروك لك لتعيين الاحتمالات للفئات ذات الصلة وتقديمها للمستخدم النهائي.

المنصات المدعومة

وتقدم TensorFlow الاستدلال واجهات برمجة التطبيقات لمعظم المنصات المشتركة المحمول / جزءا لا يتجزأ من مثل الروبوت ، دائرة الرقابة الداخلية و لينكس ، في لغات البرمجة متعددة.

في معظم الحالات ، يعكس تصميم واجهة برمجة التطبيقات (API) تفضيلًا للأداء على سهولة الاستخدام. تم تصميم TensorFlow Lite للاستدلال السريع على الأجهزة الصغيرة ، لذلك لا ينبغي أن يكون مفاجئًا أن تحاول واجهات برمجة التطبيقات تجنب النسخ غير الضرورية على حساب الراحة. وبالمثل ، فإن الاتساق مع TensorFlow APIs لم يكن هدفًا واضحًا ومن المتوقع حدوث بعض التباين بين اللغات.

عبر جميع المكتبات ، تمكّنك TensorFlow Lite API من تحميل النماذج ومدخلات التغذية واسترداد مخرجات الاستدلال.

منصة أندرويد

على نظام Android ، يمكن إجراء استدلال TensorFlow Lite باستخدام واجهات برمجة تطبيقات Java أو C ++. توفر Java APIs الراحة ويمكن استخدامها مباشرة داخل فصول نشاط Android. توفر واجهات برمجة تطبيقات C ++ مزيدًا من المرونة والسرعة ، ولكنها قد تتطلب كتابة أغلفة JNI لنقل البيانات بين طبقات Java و C ++.

انظر أدناه للحصول على تفاصيل حول استخدام C ++ و جافا ، أو اتباع التشغيل السريع الروبوت لالتعليمي، والمثال رمز.

مولد رمز المجمع TensorFlow Lite Android

لTensorFlow لايت نموذج معززة مع التعريف ، يمكن للمطورين استخدام مولد رمز المجمع TensorFlow لايت الروبوت لخلق منصة كود معين المجمع. رمز المجمع يزيل الحاجة للتفاعل مباشرة مع ByteBuffer على الروبوت. بدلا من ذلك، يمكن للمطورين التفاعل مع نموذج TensorFlow لايت مع كائنات كتابة مثل Bitmap و Rect . لمزيد من المعلومات، يرجى الرجوع إلى مولد رمز المجمع TensorFlow لايت الروبوت .

منصة iOS

في دائرة الرقابة الداخلية، TensorFlow لايت هو متاح مع المكتبات بنظام iOS مكتوب في سويفت و الهدف-C . يمكنك أيضا استخدام C API مباشرة في رموز الهدف-C.

انظر أدناه للحصول على تفاصيل حول استخدام سويفت ، الهدف-C و API C ، أو اتباع التشغيل السريع دائرة الرقابة الداخلية لتعليمي ومثال التعليمة البرمجية.

منصة لينوكس

على منصات لينكس (بما في ذلك التوت بي )، يمكنك تشغيل استدلالات باستخدام واجهات برمجة التطبيقات TensorFlow لايت المتاحة في C ++ و بايثون ، كما هو موضح في الأقسام التالية.

تشغيل نموذج

يتضمن تشغيل نموذج TensorFlow Lite بضع خطوات بسيطة:

  1. قم بتحميل النموذج في الذاكرة.
  2. بناء Interpreter على أساس النموذج القائم.
  3. تعيين قيم موتر الإدخال. (قم بتغيير حجم موتر الإدخال اختياريًا إذا كانت الأحجام المحددة مسبقًا غير مرغوبة.)
  4. استدعاء الاستدلال.
  5. قراءة قيم موتر الإخراج.

تصف الأقسام التالية كيف يمكن تنفيذ هذه الخطوات في كل لغة.

قم بتحميل وتشغيل نموذج في Java

النظام الأساسي: Android

تم تصميم API جافا لتشغيل الاستدلال مع TensorFlow لايت أساسا للاستخدام مع الروبوت، لذلك فمن متاح بوصفه والتبعية مكتبة الروبوت: org.tensorflow:tensorflow-lite .

في جاوة، عليك استخدام Interpreter فئة لتحميل الاستدلال نموذج ونموذج محرك. في كثير من الحالات ، قد يكون هذا هو API الوحيد الذي تحتاجه.

يمكنك تهيئة و Interpreter باستخدام .tflite الملف:

public Interpreter(@NotNull File modelFile);

أو مع MappedByteBuffer :

public Interpreter(@NotNull MappedByteBuffer mappedByteBuffer);

في كلتا الحالتين، يجب أن تقدم نموذجا TensorFlow لايت صحيح أو API يلقي IllegalArgumentException . إذا كنت تستخدم MappedByteBuffer تهيئة و Interpreter ، ويجب أن تبقى دون تغيير لعمر كامل من Interpreter .

الطريقة المفضلة لتشغيل الاستدلال على نموذج هي استخدام التوقيعات - متوفر للنماذج المحولة بدءًا من Tensorflow 2.5

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 طريقة يأخذ ثلاث حجج:

  • المدخلات: الخريطة للحصول على مدخلات من اسم المدخلات في التوقيع إلى كائن الإدخال.

  • المخرجات: خريطة لرسم خرائط الإخراج من اسم الانتاج في توقيع لإخراج البيانات.

  • التوقيع اسم [اختياري]: اسم التوقيع (هل يمكن أن يترك فارغا إذا كان النموذج لديه توقيع واحد).

طريقة أخرى لتشغيل استنتاج عندما لا يحتوي النموذج على توقيعات محددة. مجرد دعوة Interpreter.run() . فمثلا:

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

على run() يأخذ الطريقة فقط إدخال واحد وإرجاع ناتج واحد فقط. لذلك إذا كان النموذج الخاص بك يحتوي على مدخلات متعددة أو مخرجات متعددة ، فاستخدم بدلاً من ذلك:

interpreter.runForMultipleInputsOutputs(inputs, map_of_indices_to_outputs);

في هذه الحالة، كل دخول في inputs يناظر موتر المدخلات و map_of_indices_to_outputs خرائط مؤشرات التنسورات الإخراج إلى إخراج البيانات ذات الصلة.

في كلتا الحالتين، ينبغي للمؤشرات موتر تتوافق مع القيم التي قدمت إلى TensorFlow لايت تحويل عند إنشاء نموذج. كن على علم أن ترتيب التنسورات في input يجب أن تطابق ترتيب معين لTensorFlow لايت تحويل.

و Interpreter يوفر الفئة أيضا وظائف مريحة بالنسبة لك للحصول على مؤشر إدخال أي نموذج أو الإخراج باستخدام اسم العملية:

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

إذا opName ليست عملية صالحة في النموذج، فإنه يطرح IllegalArgumentException .

أيضا حذار أن Interpreter تملك الموارد. لتجنب حدوث تسرب للذاكرة ، يجب تحرير الموارد بعد استخدامها من خلال:

interpreter.close();

لمشروع سبيل المثال مع جافا، راجع الروبوت العينة تصنيف الصور .

أنواع البيانات المدعومة (في Java)

لاستخدام TensorFlow Lite ، يجب أن تكون أنواع البيانات لموترات الإدخال والإخراج أحد الأنواع الأولية التالية:

  • float
  • int
  • long
  • byte

String معتمدة أنواع أيضا، ولكن يتم ترميز بشكل مختلف من أنواع البدائية. على وجه الخصوص ، يحدد شكل سلسلة Tensor عدد وترتيب السلاسل في Tensor ، حيث يكون كل عنصر بحد ذاته سلسلة متغيرة الطول. في هذا المعنى، فإن (بايت) حجم العضلة الشادة لا يمكن حسابها من شكل ونوع وحده، ولا يمكن أن توفر بالتالي السلاسل ولذلك، شقة واحدة ByteBuffer حجة.

إذا أنواع البيانات الأخرى، بما في ذلك أنواع محاصر مثل Integer و Float ، وتستخدم، وهي IllegalArgumentException سيتم طرح.

المدخلات

يجب أن يكون كل المدخلات صفيف أو متعددة الأبعاد مجموعة من أنواع البدائية المعتمدة، أو الخام ByteBuffer من الحجم المناسب. إذا كان الإدخال عبارة عن مصفوفة أو مصفوفة متعددة الأبعاد ، فسيتم تغيير حجم موتر الإدخال المرتبط ضمنيًا إلى أبعاد الصفيف في وقت الاستدلال. إذا كانت المدخلات هو ByteBuffer، يجب على الطالب أولا يدويا تغيير حجم موتر المدخلات المرتبطة بها (عن طريق Interpreter.resizeInput() ) قبل تشغيل الاستدلال.

عند استخدام ByteBuffer ، ويفضل استخدام مخازن بايت مباشرة، وهذا يسمح لل Interpreter لتجنب النسخ غير الضرورية. إذا كان ByteBuffer هو عازلة بايت المباشر، يجب أن يكون أمرها ByteOrder.nativeOrder() . بعد استخدامه لاستدلال النموذج ، يجب أن يظل بدون تغيير حتى ينتهي استنتاج النموذج.

النواتج

يجب أن يكون كل ناتج مصفوفة أو مصفوفة متعددة الأبعاد من الأنواع الأولية المدعومة ، أو ByteBuffer بالحجم المناسب. لاحظ أن بعض الطرز تحتوي على مخرجات ديناميكية ، حيث يمكن أن يختلف شكل موتر الإخراج اعتمادًا على المدخلات. لا توجد طريقة مباشرة للتعامل مع هذا الأمر باستخدام واجهة برمجة تطبيقات استدلال جافا الحالية ، ولكن الإضافات المخططة ستجعل ذلك ممكنًا.

قم بتحميل وتشغيل نموذج في Swift

النظام الأساسي: iOS

و API سويفت متاح في TensorFlowLiteSwift قرنة من Cocoapods.

أولا، تحتاج إلى استيراد TensorFlowLite حدة.

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

النظام الأساسي: iOS

و API الهدف-C متاح في TensorFlowLiteObjC قرنة من Cocoapods.

أولا، تحتاج إلى استيراد TensorFlowLite حدة.

@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... */ }

استخدام C API في كود Objective-C

لا تدعم واجهة برمجة تطبيقات Objective-C حاليًا المفوضين. من أجل المندوبين استخدام مع رمز الهدف-C، تحتاج إلى الاتصال مباشرة الكامنة C 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 ++

المنصات: Android و iOS و Linux

في C ++، يتم تخزين النموذج في FlatBufferModel الصف. إنها تغلف نموذج TensorFlow Lite ويمكنك بنائه بطريقتين مختلفتين ، اعتمادًا على مكان تخزين النموذج:

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

الآن أن لديك النموذج بوصفه FlatBufferModel الكائن، يمكنك تنفيذ ذلك مع Interpreter . وحيد FlatBufferModel يمكن استخدامها في وقت واحد أكثر من Interpreter .

أجزاء مهمة من Interpreter مقتطفة أدناه API ترد في التعليمات البرمجية. وتجدر الإشارة إلى أن:

  • يتم تمثيل الموترات بأعداد صحيحة لتجنب مقارنات السلاسل (وأي تبعية ثابتة على مكتبات السلاسل).
  • يجب عدم الوصول إلى مترجم من سلاسل الرسائل المتزامنة.
  • يجب أن تسبب تخصيص الذاكرة لالمدخلات والمخرجات التنسورات بالدعوة AllocateTensors() مباشرة بعد تغيير حجم التنسورات.

يبدو أبسط استخدام لـ TensorFlow Lite مع C ++ كما يلي:

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

لمزيد من التعليمات البرمجية المثال، انظر minimal.cc و label_image.cc .

قم بتحميل وتشغيل نموذج في بايثون

النظام الأساسي: Linux

يتم توفير API بيثون لتشغيل الاستدلال في tf.lite حدة. من الذي، التي في الغالب تحتاج فقط tf.lite.Interpreter لتحميل نموذج وتشغيل الاستدلال.

يظهر المثال التالي كيفية استخدام مترجم Python لتحميل .tflite الملف وتشغيل الاستدلال مع إدخال البيانات العشوائية:

يوصى بهذا المثال إذا كنت تقوم بالتحويل من SavedModel باستخدام SignatureDef محدد. متاح بدءًا من TensorFlow 2.5

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 TFLite model in TFLite Interpreter
interpreter = tf.lite.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'])

مثال آخر إذا لم يكن لدى النموذج تعريفات SignatureDefs.

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)

كبديل لتحميل النموذج باعتباره تحويله قبل .tflite الملف، يمكنك الجمع بين الشفرة مع API TensorFlow لايت تحويل بيثون ( tf.lite.TFLiteConverter )، مما يسمح لك لتحويل نموذج TensorFlow الخاصة بك في شكل TensorFlow لايت ثم تشغيل الاستدلال:

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

لمزيد من بيثون نموذج التعليمات البرمجية، انظر label_image.py .

نصيحة: تشغيل help(tf.lite.Interpreter) في محطة بيثون للحصول على وثائق مفصلة عن المترجم.

العمليات المدعومة

يدعم TensorFlow Lite مجموعة فرعية من عمليات TensorFlow مع بعض القيود. للحصول على قائمة كاملة من العمليات والقيود رؤية الصفحة العمليات TF لايت .