Phiên bản 22.0.2 của thư viện firebase-ml-model-interpreter
giới thiệu một tính năng mới
Phương thức getLatestModelFile()
để nhận thông tin vị trí trên thiết bị tuỳ chỉnh
người mẫu. Bạn có thể dùng phương thức này để tạo thực thể trực tiếp cho TensorFlow Lite
Bạn có thể sử dụng đối tượng Interpreter
thay cho đối tượng
Trình bao bọc FirebaseModelInterpreter
.
Từ giờ trở đi, đây là phương pháp được ưu tiên sử dụng. Vì TensorFlow Lite phiên bản thông dịch viên không còn đi kèm với phiên bản thư viện Firebase, bạn linh hoạt hơn trong việc nâng cấp lên các phiên bản mới của TensorFlow Lite khi bạn muốn sử dụng hoặc dễ dàng sử dụng các bản dựng tuỳ chỉnh trên TensorFlow Lite.
Trang này hướng dẫn bạn cách di chuyển từ sử dụng FirebaseModelInterpreter
sang
TensorFlow Lite Interpreter
.
1. Cập nhật phần phụ thuộc của dự án
Cập nhật các phần phụ thuộc của dự án để bao gồm phiên bản 22.0.2 của
Thư viện firebase-ml-model-interpreter
(hoặc phiên bản mới hơn) và tensorflow-lite
thư viện:
Trước
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.1")
Sau
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.2")
implementation("org.tensorflow:tensorflow-lite:2.0.0")
2. Tạo trình thông dịch TensorFlow Lite thay vì FirebaseModelCompileer
Thay vì tạo FirebaseModelInterpreter
, hãy lấy vị trí của mô hình trên thiết bị bằng getLatestModelFile()
và sử dụng vị trí đó để tạo Interpreter
TensorFlow Lite.
Trước
Kotlin+KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
val options = FirebaseModelInterpreterOptions.Builder(remoteModel).build()
val interpreter = FirebaseModelInterpreter.getInstance(options)
Java
FirebaseCustomRemoteModel remoteModel =
new FirebaseCustomRemoteModel.Builder("your_model").build();
FirebaseModelInterpreterOptions options =
new FirebaseModelInterpreterOptions.Builder(remoteModel).build();
FirebaseModelInterpreter interpreter = FirebaseModelInterpreter.getInstance(options);
Sau
Kotlin+KTX
val remoteModel = FirebaseCustomRemoteModel.Builder("your_model").build()
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener { task ->
val modelFile = task.getResult()
if (modelFile != null) {
// Instantiate an org.tensorflow.lite.Interpreter object.
interpreter = Interpreter(modelFile)
}
}
Java
FirebaseCustomRemoteModel remoteModel =
new FirebaseCustomRemoteModel.Builder("your_model").build();
FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
.addOnCompleteListener(new OnCompleteListener<File>() {
@Override
public void onComplete(@NonNull Task<File> task) {
File modelFile = task.getResult();
if (modelFile != null) {
// Instantiate an org.tensorflow.lite.Interpreter object.
Interpreter interpreter = new Interpreter(modelFile);
}
}
});
3. Cập nhật mã chuẩn bị đầu vào và đầu ra
Với FirebaseModelInterpreter
, bạn chỉ định hình dạng đầu vào và đầu ra của mô hình
bằng cách truyền một đối tượng FirebaseModelInputOutputOptions
đến trình thông dịch khi
bạn chạy nó.
Đối với trình phiên dịch TensorFlow Lite, bạn phân bổ các đối tượng ByteBuffer
có kích thước phù hợp với đầu vào và đầu ra của mô hình.
Ví dụ: nếu mô hình của bạn có hình dạng đầu vào là các giá trị float
[1 224 224 3] và hình dạng đầu ra là các giá trị float
[1 1000], hãy thực hiện những thay đổi sau:
Trước
Kotlin+KTX
val inputOutputOptions = FirebaseModelInputOutputOptions.Builder()
.setInputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 224, 224, 3))
.setOutputFormat(0, FirebaseModelDataType.FLOAT32, intArrayOf(1, 1000))
.build()
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
// Then populate with input data.
val inputs = FirebaseModelInputs.Builder()
.add(input)
.build()
interpreter.run(inputs, inputOutputOptions)
.addOnSuccessListener { outputs ->
// ...
}
.addOnFailureListener {
// Task failed with an exception.
// ...
}
Java
FirebaseModelInputOutputOptions inputOutputOptions =
new FirebaseModelInputOutputOptions.Builder()
.setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 224, 224, 3})
.setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 1000})
.build();
float[][][][] input = new float[1][224][224][3];
// Then populate with input data.
FirebaseModelInputs inputs = new FirebaseModelInputs.Builder()
.add(input)
.build();
interpreter.run(inputs, inputOutputOptions)
.addOnSuccessListener(
new OnSuccessListener<FirebaseModelOutputs>() {
@Override
public void onSuccess(FirebaseModelOutputs result) {
// ...
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Task failed with an exception
// ...
}
});
Sau
Kotlin+KTX
val inBufferSize = 1 * 224 * 224 * 3 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val inputBuffer = ByteBuffer.allocateDirect(inBufferSize).order(ByteOrder.nativeOrder())
// Then populate with input data.
val outBufferSize = 1 * 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val outputBuffer = ByteBuffer.allocateDirect(outBufferSize).order(ByteOrder.nativeOrder())
interpreter.run(inputBuffer, outputBuffer)
Java
int inBufferSize = 1 * 224 * 224 * 3 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer inputBuffer =
ByteBuffer.allocateDirect(inBufferSize).order(ByteOrder.nativeOrder());
// Then populate with input data.
int outBufferSize = 1 * 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer outputBuffer =
ByteBuffer.allocateDirect(outBufferSize).order(ByteOrder.nativeOrder());
interpreter.run(inputBuffer, outputBuffer);
4. Cập nhật mã xử lý đầu ra
Cuối cùng, thay vì nhận kết quả của mô hình bằng FirebaseModelOutputs
phương thức getOutput()
của đối tượng, hãy chuyển đổi đầu ra ByteBuffer
thành bất kỳ
cấu trúc thuận tiện cho trường hợp sử dụng của bạn.
Ví dụ: nếu đang phân loại, bạn có thể thực hiện các thay đổi như sau:
Trước
Kotlin+KTX
val output = result.getOutput(0)
val probabilities = output[0]
try {
val reader = BufferedReader(InputStreamReader(assets.open("custom_labels.txt")))
for (probability in probabilities) {
val label: String = reader.readLine()
println("$label: $probability")
}
} catch (e: IOException) {
// File not found?
}
Java
float[][] output = result.getOutput(0);
float[] probabilities = output[0];
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(getAssets().open("custom_labels.txt")));
for (float probability : probabilities) {
String label = reader.readLine();
Log.i(TAG, String.format("%s: %1.4f", label, probability));
}
} catch (IOException e) {
// File not found?
}
Sau
Kotlin+KTX
modelOutput.rewind()
val probabilities = modelOutput.asFloatBuffer()
try {
val reader = BufferedReader(
InputStreamReader(assets.open("custom_labels.txt")))
for (i in probabilities.capacity()) {
val label: String = reader.readLine()
val probability = probabilities.get(i)
println("$label: $probability")
}
} catch (e: IOException) {
// File not found?
}
Java
modelOutput.rewind();
FloatBuffer probabilities = modelOutput.asFloatBuffer();
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(getAssets().open("custom_labels.txt")));
for (int i = 0; i < probabilities.capacity(); i++) {
String label = reader.readLine();
float probability = probabilities.get(i);
Log.i(TAG, String.format("%s: %1.4f", label, probability));
}
} catch (IOException e) {
// File not found?
}