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

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

ابدء

استيراد تبعية Gradle وإعدادات أخرى

انسخ ملف النموذج .tflite إلى دليل الأصول لوحدة Android حيث سيتم تشغيل النموذج. حدد أنه لا ينبغي ضغط الملف ، وأضف مكتبة TensorFlow Lite إلى ملف build.gradle الخاص بالوحدة:

android {
    // Other settings

    // Specify tflite file should not be compressed for the app apk
    aaptOptions {
        noCompress "tflite"
    }

}

dependencies {
    // Other dependencies

    // Import tflite dependencies
    implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
    // The GPU delegate library is optional. Depend on it as needed.
    implementation 'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly-SNAPSHOT'
    implementation 'org.tensorflow:tensorflow-lite-support:0.0.0-nightly-SNAPSHOT'
}

استكشف مكتبة دعم TensorFlow Lite AAR المستضافة في MavenCentral لإصدارات مختلفة من مكتبة الدعم.

معالجة الصور الأساسية وتحويلها

تحتوي مكتبة دعم TensorFlow Lite على مجموعة من طرق معالجة الصور الأساسية مثل الاقتصاص وتغيير الحجم. لاستخدامه ، قم بإنشاء ImagePreprocessor وأضف العمليات المطلوبة. لتحويل الصورة إلى تنسيق الموتر المطلوب بواسطة مترجم TensorFlow Lite ، قم بإنشاء TensorImage لاستخدامه كمدخل:

import org.tensorflow.lite.DataType;
import org.tensorflow.lite.support.image.ImageProcessor;
import org.tensorflow.lite.support.image.TensorImage;
import org.tensorflow.lite.support.image.ops.ResizeOp;

// Initialization code
// Create an ImageProcessor with all ops required. For more ops, please
// refer to the ImageProcessor Architecture section in this README.
ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR))
        .build();

// Create a TensorImage object. This creates the tensor of the corresponding
// tensor type (uint8 in this case) that the TensorFlow Lite interpreter needs.
TensorImage tensorImage = new TensorImage(DataType.UINT8);

// Analysis code for every frame
// Preprocess the image
tensorImage.load(bitmap);
tensorImage = imageProcessor.process(tensorImage);

يمكن قراءة نوع بيانات DataType من خلال مكتبة مستخرج البيانات الوصفية بالإضافة إلى معلومات النموذج الأخرى.

معالجة البيانات الصوتية الأساسية

تحدد مكتبة دعم TensorFlow Lite أيضًا فئة TensorAudio بعض طرق معالجة البيانات الصوتية الأساسية. يتم استخدامه في الغالب مع AudioRecord ويلتقط عينات صوتية في مخزن حلقي مؤقت.

import android.media.AudioRecord;
import org.tensorflow.lite.support.audio.TensorAudio;

// Create an `AudioRecord` instance.
AudioRecord record = AudioRecord(...)

// Create a `TensorAudio` object from Android AudioFormat.
TensorAudio tensorAudio = new TensorAudio(record.getFormat(), size)

// Load all audio samples available in the AudioRecord without blocking.
tensorAudio.load(record)

// Get the `TensorBuffer` for inference.
TensorBuffer buffer = tensorAudio.getTensorBuffer()

إنشاء كائنات الإخراج وتشغيل النموذج

قبل تشغيل النموذج ، نحتاج إلى إنشاء كائنات الحاوية التي ستخزن النتيجة:

import org.tensorflow.lite.DataType;
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;

// Create a container for the result and specify that this is a quantized model.
// Hence, the 'DataType' is defined as UINT8 (8-bit unsigned integer)
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

تحميل النموذج وتشغيل الاستدلال:

import java.nio.MappedByteBuffer;
import org.tensorflow.lite.InterpreterFactory;
import org.tensorflow.lite.InterpreterApi;

// Initialise the model
try{
    MappedByteBuffer tfliteModel
        = FileUtil.loadMappedFile(activity,
            "mobilenet_v1_1.0_224_quant.tflite");
    InterpreterApi tflite = new InterpreterFactory().create(
        tfliteModel, new InterpreterApi.Options());
} catch (IOException e){
    Log.e("tfliteSupport", "Error reading model", e);
}

// Running inference
if(null != tflite) {
    tflite.run(tImage.getBuffer(), probabilityBuffer.getBuffer());
}

الوصول إلى النتيجة

يمكن للمطورين الوصول إلى المخرجات مباشرة من خلال probabilityBuffer.getFloatArray() . إذا كان النموذج ينتج مخرجات كمية ، تذكر أن تقوم بتحويل النتيجة. بالنسبة لنموذج MobileNet الكمي ، يحتاج المطور إلى تقسيم كل قيمة ناتجة على 255 للحصول على احتمال يتراوح من 0 (أقل احتمالًا) إلى 1 (على الأرجح) لكل فئة.

اختياري: تعيين النتائج إلى التصنيفات

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

import org.tensorflow.lite.support.common.FileUtil;

final String ASSOCIATED_AXIS_LABELS = "labels.txt";
List<String> associatedAxisLabels = null;

try {
    associatedAxisLabels = FileUtil.loadLabels(this, ASSOCIATED_AXIS_LABELS);
} catch (IOException e) {
    Log.e("tfliteSupport", "Error reading label file", e);
}

يوضح المقتطف التالي كيفية إقران الاحتمالات بتسميات الفئات:

import java.util.Map;
import org.tensorflow.lite.support.common.TensorProcessor;
import org.tensorflow.lite.support.common.ops.NormalizeOp;
import org.tensorflow.lite.support.label.TensorLabel;

// Post-processor which dequantize the result
TensorProcessor probabilityProcessor =
    new TensorProcessor.Builder().add(new NormalizeOp(0, 255)).build();

if (null != associatedAxisLabels) {
    // Map of labels and their corresponding probability
    TensorLabel labels = new TensorLabel(associatedAxisLabels,
        probabilityProcessor.process(probabilityBuffer));

    // Create a map to access the result based on label
    Map<String, Float> floatMap = labels.getMapWithFloatValue();
}

تغطية حالة الاستخدام الحالية

يغطي الإصدار الحالي من مكتبة دعم TensorFlow Lite ما يلي:

  • أنواع البيانات الشائعة (تعويم ، uint8 ، صور ، صوت ومجموعة من هذه الكائنات) كمدخلات ومخرجات لنماذج tflite.
  • عمليات الصورة الأساسية (اقتصاص الصورة وتغيير حجمها وتدويرها).
  • التطبيع والتكميم
  • أدوات الملف

ستعمل الإصدارات المستقبلية على تحسين دعم التطبيقات المتعلقة بالنص.

هندسة معالج الصور

سمح تصميم ImageProcessor بتحديد عمليات معالجة الصور مسبقًا وتحسينها أثناء عملية الإنشاء. يدعم ImageProcessor حاليًا ثلاث عمليات أساسية للمعالجة المسبقة ، كما هو موضح في التعليقات الثلاثة في مقتطف الشفرة أدناه:

import org.tensorflow.lite.support.common.ops.NormalizeOp;
import org.tensorflow.lite.support.common.ops.QuantizeOp;
import org.tensorflow.lite.support.image.ops.ResizeOp;
import org.tensorflow.lite.support.image.ops.ResizeWithCropOrPadOp;
import org.tensorflow.lite.support.image.ops.Rot90Op;

int width = bitmap.getWidth();
int height = bitmap.getHeight();

int size = height > width ? width : height;

ImageProcessor imageProcessor =
    new ImageProcessor.Builder()
        // Center crop the image to the largest square possible
        .add(new ResizeWithCropOrPadOp(size, size))
        // Resize using Bilinear or Nearest neighbour
        .add(new ResizeOp(224, 224, ResizeOp.ResizeMethod.BILINEAR));
        // Rotation counter-clockwise in 90 degree increments
        .add(new Rot90Op(rotateDegrees / 90))
        .add(new NormalizeOp(127.5, 127.5))
        .add(new QuantizeOp(128.0, 1/128.0))
        .build();

شاهد المزيد من التفاصيل هنا حول التطبيع والكمية.

الهدف النهائي لمكتبة الدعم هو دعم جميع تحويلات tf.image . هذا يعني أن التحويل سيكون هو نفسه TensorFlow وسيكون التنفيذ مستقلاً عن نظام التشغيل.

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

توضيح

عند بدء كائنات الإدخال أو الإخراج مثل TensorImage أو TensorBuffer ، يلزمك تحديد أنواعها لتكون DataType.UINT8 أو DataType.FLOAT32 .

TensorImage tensorImage = new TensorImage(DataType.UINT8);
TensorBuffer probabilityBuffer =
    TensorBuffer.createFixedSize(new int[]{1, 1001}, DataType.UINT8);

يمكن استخدام TensorProcessor الإدخال أو إزالة موترات الإخراج. على سبيل المثال ، عند معالجة مخرجات TensorBuffer ، يمكن للمطور استخدام DequantizeOp لإزالة النتيجة إلى احتمال النقطة العائمة بين 0 و 1:

import org.tensorflow.lite.support.common.TensorProcessor;

// Post-processor which dequantize the result
TensorProcessor probabilityProcessor =
    new TensorProcessor.Builder().add(new DequantizeOp(0, 1/255.0)).build();
TensorBuffer dequantizedBuffer = probabilityProcessor.process(probabilityBuffer);

يمكن قراءة معلمات تكميم الموتر من خلال مكتبة مستخرج البيانات الوصفية .