ประมวลผลข้อมูลอินพุตและเอาต์พุตด้วย LiteRT Support Library

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

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

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

คัดลอกไฟล์โมเดล .tflite ไปยังไดเรกทอรี Asset ของโมดูล Android ตำแหน่งที่โมเดลจะทำงาน ระบุว่าไม่ควรบีบอัดไฟล์ และ เพิ่มไลบรารี LiteRT ลงในไฟล์ 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 'com.google.ai.edge.litert:litert-gpu:0.0.0-nightly-SNAPSHOT'
    implementation 'com.google.ai.edge.litert:litert-support:0.0.0-nightly-SNAPSHOT'
}

สำรวจ AAR ของไลบรารีการสนับสนุน LiteRT ที่ MavenCentral สำหรับ Support Library เวอร์ชันต่างๆ

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

LiteRT Support Library มีชุดการปรับแต่งอิมเมจขั้นพื้นฐาน เช่น ครอบตัดและปรับขนาด หากต้องการใช้ ให้สร้าง ImagePreprocessor และ เพิ่มการดำเนินการที่จำเป็น วิธีแปลงรูปภาพเป็นรูปแบบ tensor ที่ล่าม LiteRT กำหนด ให้สร้าง 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 LiteRT interpreter needs.
TensorImage tensorImage = new TensorImage(DataType.UINT8);

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

DataType ของ tensor สามารถอ่านผ่าน ไลบรารีเครื่องมือแยกข้อมูลเมตา รวมทั้งข้อมูลรุ่นอื่นๆ

การประมวลผลข้อมูลเสียงพื้นฐาน

LiteRT Support Library ยังกำหนดการรวม 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();
}

ความครอบคลุมของ Use Case ปัจจุบัน

LiteRT Support Library เวอร์ชันปัจจุบันครอบคลุมเนื้อหาต่อไปนี้

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

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

สถาปัตยกรรมโปรเซสเซอร์ภาพ

การออกแบบของ ImageProcessor ช่วยให้การดำเนินการปรับเปลี่ยนรูปภาพสามารถ กำหนดล่วงหน้าและเพิ่มประสิทธิภาพระหว่างขั้นตอนการสร้าง ImageProcessor ปัจจุบันรองรับการดำเนินการประมวลผลล่วงหน้าพื้นฐาน 3 แบบตามที่อธิบายไว้ใน ความคิดเห็นสามรายการในข้อมูลโค้ดด้านล่าง

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 เพื่อวัดปริมาณอินพุตหรือลดปริมาณเอาต์พุตได้ Tensor ตัวอย่างเช่น เมื่อประมวลผลเอาต์พุตที่เล็กลง 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);

พารามิเตอร์การแปลงปริมาณของ Tensor สามารถอ่านได้ผ่าน ไลบรารีเครื่องมือแยกข้อมูลเมตา