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

นักพัฒนาแอปพลิเคชันบนอุปกรณ์เคลื่อนที่มักจะโต้ตอบกับออบเจ็กต์ที่พิมพ์ไว้ เช่น อัตราบิตหรือแบบพื้นฐาน เช่น จำนวนเต็ม อย่างไรก็ตาม API อินเทอร์พรีเตอร์ของ TensorFlow Lite ที่เรียกใช้โมเดลแมชชีนเลิร์นนิงในอุปกรณ์ใช้ Tensor ในรูปแบบของ 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 Support Library AAR ที่ฝากไว้ที่ MavenCentral เพื่อดูไลบรารี Support Library เวอร์ชันต่างๆ

การปรับแต่งและการแปลงรูปภาพเบื้องต้น

ไลบรารีการสนับสนุนของ TensorFlow Lite มีชุดวิธีจัดการรูปภาพพื้นฐาน เช่น การครอบตัดและปรับขนาด หากต้องการใช้งาน ให้สร้าง ImagePreprocessor และเพิ่มการดำเนินการที่จำเป็น หากต้องการแปลงอิมเมจเป็นรูปแบบ tensor ที่ตัวแปลของ 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 ของ Tensor ได้ในไลบรารีเครื่องมือแยกข้อมูลเมตา รวมถึงข้อมูลโมเดลอื่นๆ

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

ไลบรารีการสนับสนุนของ 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();
}

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

ไลบรารีการสนับสนุนของ TensorFlow Lite เวอร์ชันปัจจุบันครอบคลุมสิ่งต่อไปนี้

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

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

สถาปัตยกรรมตัวประมวลผลภาพ

การออกแบบ ImageProcessor ช่วยให้มีการกำหนดการดำเนินการปรับแต่งรูปภาพไว้ด้านหน้าและเพิ่มประสิทธิภาพระหว่างกระบวนการบิลด์ ปัจจุบัน ImageProcessor รองรับการดำเนินการก่อนการประมวลผลเบื้องต้น 3 แบบ ตามที่อธิบายไว้ใน 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 อินพุตหรือจัดลำดับ tensors เอาต์พุต เช่น เมื่อประมวลผลเอาต์พุตเชิงปริมาณ 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 ได้ในไลบรารีเครื่องมือแยกข้อมูลเมตา