โดยปกติแล้ว นักพัฒนาแอปพลิเคชันบนอุปกรณ์เคลื่อนที่จะโต้ตอบกับออบเจ็กต์ที่มีการพิมพ์ เช่น บิตแมป หรือไพรม์ เช่น จำนวนเต็ม อย่างไรก็ตาม API ของตัวแปล LiteRT ที่เรียกใช้โมเดลแมชชีนเลิร์นนิงในอุปกรณ์จะใช้เทนเซอร์ในรูปแบบ ByteBuffer ซึ่งอาจแก้ไขข้อบกพร่องและจัดการได้ยาก ไลบรารีการรองรับ LiteRT Android ออกแบบมาเพื่อช่วยประมวลผลอินพุตและเอาต์พุตของโมเดล LiteRT และทำให้ตัวตีความ LiteRT ใช้งานง่ายขึ้น
เริ่มต้นใช้งาน
นำเข้าทรัพยากร Dependency ของ Gradle และการตั้งค่าอื่นๆ
คัดลอก.tfliteไฟล์โมเดลไปยังไดเรกทอรีชิ้นงานของโมดูล 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 สำหรับไลบรารีการรองรับเวอร์ชันต่างๆ
การปรับแต่งและแปลงรูปภาพขั้นพื้นฐาน
ไลบรารีการรองรับ LiteRT มีชุดวิธีการจัดการรูปภาพพื้นฐาน เช่น ครอบตัดและปรับขนาด หากต้องการใช้ ให้สร้าง ImagePreprocessor แล้วเพิ่มการดำเนินการที่จำเป็น หากต้องการแปลงรูปภาพเป็นรูปแบบเทนเซอร์ที่ตัวแปล 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 ของเทนเซอร์สามารถอ่านได้ผ่านไลบรารี
โปรแกรมแยกข้อมูลเมตา รวมถึงข้อมูลโมเดลอื่นๆ
การประมวลผลข้อมูลเสียงพื้นฐาน
ไลบรารีการสนับสนุน LiteRT ยังกำหนดคลาส TensorAudio ที่ครอบคลุมเมธอดการประมวลผลข้อมูลเสียงพื้นฐานบางอย่างด้วย
โดยส่วนใหญ่จะใช้ร่วมกับ
AudioRecord
และบันทึกตัวอย่างเสียงใน Ring Buffer
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();
}
ความครอบคลุมของกรณีการใช้งานปัจจุบัน
ไลบรารีการสนับสนุน LiteRT เวอร์ชันปัจจุบันครอบคลุมสิ่งต่อไปนี้
- ประเภทข้อมูลทั่วไป (float, uint8, รูปภาพ, เสียง และอาร์เรย์ของออบเจ็กต์เหล่านี้) เป็นอินพุตและเอาต์พุตของโมเดล TFLite
- การดำเนินการกับรูปภาพขั้นพื้นฐาน (ครอบตัดรูปภาพ ปรับขนาด และหมุน)
- การแปลงเป็นรูปแบบมาตรฐานและการหาปริมาณ
- file utils
เวอร์ชันในอนาคตจะปรับปรุงการรองรับแอปพลิเคชันที่เกี่ยวข้องกับข้อความ
สถาปัตยกรรม ImageProcessor
การออกแบบของ 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 สามารถใช้เพื่อควอนไทซ์อินพุตเทนเซอร์หรือดีควอนไทซ์เอาต์พุต
เทนเซอร์ได้ ตัวอย่างเช่น เมื่อประมวลผลเอาต์พุตที่ผ่านการควอนไทซ์ 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);
คุณอ่านพารามิเตอร์การหาปริมาณของเทนเซอร์ได้ผ่านไลบรารี ตัวแยก ข้อมูลเมตา