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

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

  • أنواع البيانات الشائعة (float، 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);

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