Если в вашем приложении используются собственные модели TensorFlow Lite, вы можете развернуть их с помощью Firebase ML. Развертывание моделей с помощью Firebase позволяет уменьшить размер приложения при скачивании и обновлять модели машинного обучения без выпуска новой версии приложения. Кроме того, с помощью Remote Config и A/B Testing вы можете динамически предоставлять разные модели разным группам пользователей.
Модели TensorFlow Lite
Модели TensorFlow Lite – это модели машинного обучения, оптимизированные для работы на мобильных устройствах. Чтобы получить модель TensorFlow Lite:
- Использовать готовую модель, например одну из официальных моделей TensorFlow Lite.
- Преобразуйте модель TensorFlow, модель Keras или конкретную функцию в TensorFlow Lite.
Подготовка
- Если вы ещё этого не сделали, добавьте Firebase в проект для Android.
-
В файле Gradle на уровне модуля (приложения) (обычно
<project>/<app-module>/build.gradle.ktsили<project>/<app-module>/build.gradle) добавьте зависимость для библиотеки загрузчика моделей Firebase ML для Android. Для управления версиями библиотек рекомендуется использовать Firebase Android BoM.Кроме того, при настройке загрузчика моделей Firebase ML вам нужно добавить в приложение TensorFlow Lite SDK.
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:35.1.0")) // Add the dependency for the Firebase ML model downloader library // When using the BoM, you don't specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-ml-modeldownloader")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") }Благодаря Firebase Android BoM в вашем приложении всегда будут использоваться совместимые версии библиотек Firebase Android.
(Альтернативный вариант) Добавьте зависимости библиотеки Firebase без использования BoM.
Если вы не хотите использовать Firebase BoM, вам нужно будет указать версию каждой библиотеки Firebase в строке зависимости.
Если вы используете в приложении несколько библиотек Firebase, настоятельно рекомендуем управлять их версиями с помощью BoM. Это позволит обеспечить совместимость всех версий.
dependencies { // Add the dependency for the Firebase ML model downloader library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-ml-modeldownloader:26.1.1")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") } - В манифесте приложения укажите, что требуется разрешение INTERNET:
<uses-permission android:name="android.permission.INTERNET" />
1. Разверните модель
Разверните собственные модели TensorFlow с помощью консоли Firebase или Firebase Admin SDK для Python и Node.js. Подробнее о том, как развертывать собственные модели и управлять ими…
После добавления пользовательской модели в проект Firebase вы можете ссылаться на нее в своих приложениях, используя указанное вами имя. Вы можете в любой момент развернуть новую модель TensorFlow Lite и скачать ее на устройства пользователей, вызвав getModel() (см. ниже).
2. Скачайте модель на устройство и инициализируйте интерпретатор TensorFlow Lite.
Чтобы использовать модель TensorFlow Lite в приложении, сначала скачайте ее последнюю версию на устройство с помощью SDK Firebase ML. Затем создайте экземпляр интерпретатора TensorFlow Lite с моделью.Чтобы начать скачивание модели, вызовите метод getModel() загрузчика моделей, указав имя, которое вы присвоили модели при ее загрузке, хотите ли вы всегда скачивать последнюю версию модели и условия, при которых вы хотите разрешить скачивание.
Вы можете выбрать один из трех вариантов скачивания:
| Тип скачивания | Описание |
|---|---|
| LOCAL_MODEL | Получите локальную модель с устройства.
Если локальная модель недоступна, этот метод работает так же, как LATEST_MODEL. Используйте этот тип скачивания, если вы не хотите проверять наличие обновлений модели. Например, вы используете Remote Config для получения названий моделей и всегда загружаете модели под новыми названиями (рекомендуется). |
| LOCAL_MODEL_UPDATE_IN_BACKGROUND | Получите локальную модель с устройства и начните обновлять ее в фоновом режиме.
Если локальная модель недоступна, этот метод работает так же, как LATEST_MODEL. |
| LATEST_MODEL | Получите доступ к новейшей модели. Если локальная модель является последней версией, возвращает локальную модель. В противном случае скачайте последнюю версию. В этом случае загрузка API заблокирует все другие операции до момента загрузки последней версии (не рекомендуется). Используйте этот вариант, только если вам действительно нужна последняя версия. |
Пока модель не скачана, отключите связанные с ней функции, например сделайте серыми или скройте элементы интерфейса.
Kotlin
val conditions = CustomModelDownloadConditions.Builder()
.requireWifi() // Also possible: .requireCharging() and .requireDeviceIdle()
.build()
FirebaseModelDownloader.getInstance()
.getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND,
conditions)
.addOnSuccessListener { model: CustomModel? ->
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
// The CustomModel object contains the local path of the model file,
// which you can use to instantiate a TensorFlow Lite interpreter.
val modelFile = model?.file
if (modelFile != null) {
interpreter = Interpreter(modelFile)
}
}
Java
CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder()
.requireWifi() // Also possible: .requireCharging() and .requireDeviceIdle()
.build();
FirebaseModelDownloader.getInstance()
.getModel("your_model", DownloadType.LOCAL_MODEL_UPDATE_IN_BACKGROUND, conditions)
.addOnSuccessListener(new OnSuccessListener<CustomModel>() {
@Override
public void onSuccess(CustomModel model) {
// Download complete. Depending on your app, you could enable the ML
// feature, or switch from the local model to the remote model, etc.
// The CustomModel object contains the local path of the model file,
// which you can use to instantiate a TensorFlow Lite interpreter.
File modelFile = model.getFile();
if (modelFile != null) {
interpreter = new Interpreter(modelFile);
}
}
});
Во многих приложениях скачивание запускается в коде инициализации, но вы можете сделать это в любой момент до того, как вам понадобится использовать модель.
3. Выполните вывод на основе входных данных.
Получите формы входных и выходных данных модели
Интерпретатор модели TensorFlow Lite принимает на входе и выдает на выходе один или несколько многомерных массивов. Эти массивы содержат значения byte, int, long или float. Прежде чем передавать данные в модель или использовать ее результат, необходимо знать количество и размеры ("форму") массивов, которые использует ваша модель.
Если вы создали модель самостоятельно или у вас есть документация по форматам входных и выходных данных, то у вас уже может быть эта информация. Если вы не знаете форму и тип данных входных и выходных данных вашей модели, вы можете использовать интерпретатор TensorFlow Lite для проверки вашей модели. Пример:
Python
import tensorflow as tf interpreter = tf.lite.Interpreter(model_path="your_model.tflite") interpreter.allocate_tensors() # Print input shape and type inputs = interpreter.get_input_details() print('{} input(s):'.format(len(inputs))) for i in range(0, len(inputs)): print('{} {}'.format(inputs[i]['shape'], inputs[i]['dtype'])) # Print output shape and type outputs = interpreter.get_output_details() print('\n{} output(s):'.format(len(outputs))) for i in range(0, len(outputs)): print('{} {}'.format(outputs[i]['shape'], outputs[i]['dtype']))
Пример выходных данных:
1 input(s): [ 1 224 224 3] <class 'numpy.float32'> 1 output(s): [1 1000] <class 'numpy.float32'>
Запустите интерпретатор
Определив формат входных и выходных данных модели, получите входные данные и выполните все преобразования данных, необходимые для получения входных данных правильной формы для вашей модели.Например, если у вас есть модель классификации изображений с входной формой из [1 224 224 3] значений с плавающей запятой, вы можете сгенерировать входной ByteBuffer из объекта Bitmap, как показано в следующем примере:
Kotlin
val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true)
val input = ByteBuffer.allocateDirect(224*224*3*4).order(ByteOrder.nativeOrder())
for (y in 0 until 224) {
for (x in 0 until 224) {
val px = bitmap.getPixel(x, y)
// Get channel values from the pixel value.
val r = Color.red(px)
val g = Color.green(px)
val b = Color.blue(px)
// Normalize channel values to [-1.0, 1.0]. This requirement depends on the model.
// For example, some models might require values to be normalized to the range
// [0.0, 1.0] instead.
val rf = (r - 127) / 255f
val gf = (g - 127) / 255f
val bf = (b - 127) / 255f
input.putFloat(rf)
input.putFloat(gf)
input.putFloat(bf)
}
}
Java
Bitmap bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true);
ByteBuffer input = ByteBuffer.allocateDirect(224 * 224 * 3 * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < 224; y++) {
for (int x = 0; x < 224; x++) {
int px = bitmap.getPixel(x, y);
// Get channel values from the pixel value.
int r = Color.red(px);
int g = Color.green(px);
int b = Color.blue(px);
// Normalize channel values to [-1.0, 1.0]. This requirement depends
// on the model. For example, some models might require values to be
// normalized to the range [0.0, 1.0] instead.
float rf = (r - 127) / 255.0f;
float gf = (g - 127) / 255.0f;
float bf = (b - 127) / 255.0f;
input.putFloat(rf);
input.putFloat(gf);
input.putFloat(bf);
}
}
Затем выделите ByteBuffer, достаточно большой, чтобы содержать выходные данные модели, и передайте входной и выходной буферы методу run() интерпретатора TensorFlow Lite. Например, для выходной формы из [1 1000] значений с плавающей запятой:
Kotlin
val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE
val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder())
interpreter?.run(input, modelOutput)
Java
int bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE;
ByteBuffer modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder());
interpreter.run(input, modelOutput);
Как использовать выходные данные, зависит от модели.
Например, если вы выполняете классификацию, в качестве следующего шага вы можете сопоставить индексы результата с метками, которые они представляют:
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?
}
Приложение. Безопасность модели
Независимо от того, как вы предоставляете доступ к моделям TensorFlow Lite для Firebase ML, Firebase ML хранит их в стандартном сериализованном формате protobuf в локальном хранилище.
Теоретически это означает, что любой может скопировать вашу модель. Однако на практике большинство моделей настолько специфичны для конкретного приложения и запутаны оптимизацией, что риск аналогичен тому, что конкуренты разберут и повторно используют ваш код. Тем не менее, вы должны знать об этом риске, прежде чем использовать пользовательскую модель в своем приложении.
На устройствах с Android API уровня 21 (Lollipop) и более поздних версий модель скачивается в каталог, который исключен из автоматического резервного копирования.
На устройствах с Android API уровня 20 и ниже модель скачивается в каталог com.google.firebase.ml.custom.models во внутреннем хранилище приложения. Если вы включили резервное копирование файлов с помощью BackupAgent, вы можете исключить этот каталог.