ประมวลผลข้อมูลอินพุตและเอาต์พุตด้วยไลบรารีสนับสนุน TensorFlow Lite

นักพัฒนาแอปพลิเคชันมือถือมักจะโต้ตอบกับออบเจ็กต์ที่พิมพ์เช่นบิตแมปหรือแบบดั้งเดิมเช่นจำนวนเต็ม อย่างไรก็ตาม TensorFlow Lite Interpreter ที่รันโมเดลแมชชีนเลิร์นนิงบนอุปกรณ์จะใช้เทนเซอร์ในรูปแบบของ ByteBuffer ซึ่งอาจเป็นเรื่องยากที่จะดีบักและจัดการ TensorFlow Lite Android Support Library ได้รับการออกแบบมาเพื่อช่วยประมวลผลอินพุตและเอาต์พุตของโมเดล TensorFlow Lite และทำให้ล่าม TensorFlow Lite ใช้งานได้ง่ายขึ้น

เริ่มต้นใช้งาน

นำเข้า Gradle dependency และการตั้งค่าอื่น ๆ

คัดลอกไฟล์โมเดล. .tflite ไปยังไดเร็กทอรี assets ของโมดูล 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 Support Library AAR ที่โฮสต์ที่ MavenCentral สำหรับไลบรารี Support เวอร์ชันต่างๆ

การจัดการและการแปลงรูปภาพขั้นพื้นฐาน

ไลบรารีการสนับสนุน TensorFlow Lite มีชุดวิธีการจัดการรูปภาพขั้นพื้นฐานเช่นการครอบตัดและปรับขนาด ในการใช้งานให้สร้าง ImagePreprocessor และเพิ่มการดำเนินการที่จำเป็น ในการแปลงภาพเป็นรูปแบบเทนเซอร์ที่ต้องการโดยล่าม TensorFlow Lite ให้สร้าง TensorImage เพื่อใช้เป็นอินพุต:

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 ของเทนเซอร์สามารถอ่านผ่าน ไลบรารี metadata exractor รวมถึงข้อมูลโมเดลอื่น ๆ

การประมวลผลข้อมูลเสียง Baisc

ไลบรารีการสนับสนุน TensorFlow Lite ยังกำหนดคลาส TensorAudio ตัดวิธีการประมวลผลข้อมูลเสียงพื้นฐานบางอย่าง ส่วนใหญ่จะใช้ร่วมกับ 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.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 org.tensorflow.lite.support.model.Model;

// Initialise the model
try{
    MappedByteBuffer tfliteModel
        = FileUtil.loadMappedFile(activity,
            "mobilenet_v1_1.0_224_quant.tflite");
    Interpreter tflite = new Interpreter(tfliteModel)
} 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 org.tensorflow.lite.support.common.TensorProcessor;
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 Support Library เวอร์ชันปัจจุบันครอบคลุม:

  • ชนิดข้อมูลทั่วไป (float, uint8, รูปภาพ, เสียงและอาร์เรย์ของวัตถุเหล่านี้) เป็นอินพุตและเอาต์พุตของโมเดล tflite
  • การใช้งานภาพพื้นฐาน (ครอบตัดภาพปรับขนาดและหมุน)
  • การทำให้เป็นมาตรฐานและการหาปริมาณ
  • ยูทิลิตี้ไฟล์

เวอร์ชันในอนาคตจะปรับปรุงการรองรับแอปพลิเคชันที่เกี่ยวข้องกับข้อความ

สถาปัตยกรรม ImageProcessor

การออกแบบของ ImageProcessor อนุญาตให้กำหนดการดำเนินการปรับแต่งภาพไว้ข้างหน้าและปรับให้เหมาะสมในระหว่างขั้นตอนการสร้าง ปัจจุบัน ImageProcessor รองรับการประมวลผลขั้นพื้นฐานสามขั้นตอน:

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

พารามิเตอร์การหาปริมาณของเทนเซอร์สามารถอ่านได้ผ่าน ไลบรารี metadata exractor