В версии 22.0.2 библиотеки firebase-ml-model-interpreter появился новый метод getLatestModelFile() , который получает местоположение пользовательских моделей на устройстве. Этот метод можно использовать для непосредственного создания объекта TensorFlow Lite Interpreter , который можно использовать вместо обёртки FirebaseModelInterpreter .
В дальнейшем этот подход будет предпочтительным. Поскольку версия интерпретатора TensorFlow Lite больше не связана с версией библиотеки Firebase, у вас будет больше гибкости для обновления до новых версий TensorFlow Lite в любое время или будет проще использовать пользовательские сборки TensorFlow Lite.
 На этой странице показано, как можно перейти от использования FirebaseModelInterpreter к TensorFlow Lite Interpreter .
1. Обновите зависимости проекта
 Обновите зависимости вашего проекта, включив версию 22.0.2 библиотеки firebase-ml-model-interpreter (или более новую) и библиотеку tensorflow-lite :
До
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.1")
После
implementation("com.google.firebase:firebase-ml-model-interpreter:22.0.2")
implementation("org.tensorflow:tensorflow-lite:2.0.0")
2. Создайте интерпретатор TensorFlow Lite вместо FirebaseModelInterpreter.
 Вместо создания FirebaseModelInterpreter получите местоположение модели на устройстве с помощью getLatestModelFile() и используйте его для создания TensorFlow Lite Interpreter .
До
Kotlin
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);
После
Kotlin
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. Обновите код подготовки входных и выходных данных.
 С помощью FirebaseModelInterpreter вы указываете входные и выходные формы модели, передавая объект FirebaseModelInputOutputOptions интерпретатору при его запуске.
 Для интерпретатора TensorFlow Lite вместо этого вы выделяете объекты ByteBuffer нужного размера для входных и выходных данных вашей модели.
 Например, если ваша модель имеет входную форму [1 224 224 3] значений float и выходную форму [1 1000] значений float , внесите следующие изменения:
До
Kotlin
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
                        // ...
                    }
                });
После
Kotlin
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. Обновите код обработки вывода.
 Наконец, вместо того, чтобы получать выходные данные модели с помощью метода getOutput() объекта FirebaseModelOutputs , преобразуйте выходные данные ByteBuffer в любую удобную для вашего варианта использования структуру.
Например, если вы проводите классификацию, вы можете внести следующие изменения:
До
Kotlin
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?
}
После
Kotlin
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?
}