Library firebase-ml-model-interpreter
versi 22.0.2 memperkenalkan metode getLatestModelFile()
baru, yang mendapatkan lokasi pada perangkat model kustom. Anda dapat menggunakan metode ini untuk langsung membuat instance objek Interpreter
TensorFlow Lite, yang dapat digunakan sebagai pengganti wrapper FirebaseModelInterpreter
.
Untuk selanjutnya, ini adalah pendekatan yang diutamakan. Karena versi penafsir TensorFlow Lite tidak lagi disatukan dengan versi library Firebase, Anda memiliki fleksibilitas lebih tinggi untuk mengupgrade ke versi baru TensorFlow Lite jika diinginkan, atau lebih mudah menggunakan build TensorFlow Lite kustom.
Halaman ini menunjukkan cara bermigrasi dari FirebaseModelInterpreter
ke Interpreter
TensorFlow Lite.
1. Memperbarui dependensi project
Perbarui dependensi project Anda untuk menyertakan library firebase-ml-model-interpreter
versi 22.0.2 (atau yang lebih baru) dan library tensorflow-lite
:
Sebelum
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.1")
Setelah
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.2")
implementation("org.tensorflow:tensorflow-lite:2.0.0")
2. Membuat penafsir TensorFlow Lite, bukan FirebaseModelInterpreter
Alih-alih membuat FirebaseModelInterpreter
, dapatkan lokasi model di perangkat dengan getLatestModelFile()
dan gunakan untuk membuat Interpreter
TensorFlow Lite.
Sebelum
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);
Setelah
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. Memperbarui kode persiapan input dan output
Dengan FirebaseModelInterpreter
, tentukan bentuk input dan output model dengan meneruskan objek FirebaseModelInputOutputOptions
ke penafsir saat Anda menjalankannya.
Untuk penafsir TensorFlow Lite, sebaiknya alokasikan objek ByteBuffer
dengan ukuran yang tepat untuk input dan output model Anda.
Misalnya, jika model Anda memiliki bentuk input dari nilai float
[1 224 224 3] dan bentuk output dari nilai float
[1 1000], maka lakukan perubahan berikut:
Sebelum
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
// ...
}
});
Setelah
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. Memperbarui kode penanganan output
Terakhir, alih-alih mendapatkan output model dengan metode getOutput()
objek FirebaseModelOutputs
, konversikan output ByteBuffer
ke struktur apa pun yang sesuai untuk kasus penggunaan Anda.
Misalnya, jika melakukan klasifikasi, Anda dapat membuat perubahan seperti berikut:
Sebelum
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?
}
Setelah
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?
}