如果您的應用程式使用自訂TensorFlow Lite模型,您可以使用 Firebase ML 來部署模型。透過使用 Firebase 部署模型,您可以減少應用程式的初始下載大小並更新套用的 ML 模型,而無需發布應用程式的新版本。而且,透過遠端配置和 A/B 測試,您可以動態地為不同的使用者群組提供不同的模型。
TensorFlow Lite 模型
TensorFlow Lite 模型是經過最佳化以在行動裝置上運行的 ML 模型。若要取得 TensorFlow Lite 模型:
在你開始之前
- 如果您尚未將 Firebase 新增至您的 Android 專案中,請將其新增至您的 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:32.8.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 程式庫的相容版本。
正在尋找 Kotlin 特定的庫模組?從2023 年 10 月(Firebase BoM 32.5.0)開始,Kotlin 和 Java 開發人員都可以依賴主庫模組(有關詳細信息,請參閱有關此計劃的常見問題解答)。(替代方法)在不使用 BoM 的情況下新增 Firebase 庫依賴項
如果您選擇不使用 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:24.2.3")
// 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. 部署您的模型
使用 Firebase 控制台或 Firebase 管理 Python 和 Node.js SDK 部署自訂 TensorFlow 模型。請參閱部署和管理自訂模型。
將自訂模型新增至 Firebase 專案後,您可以使用指定的名稱在應用程式中引用該模型。您可以隨時部署新的 TensorFlow Lite 模型,並透過呼叫getModel()
將新模型下載到使用者的裝置上(請參閱下文)。
2. 將模型下載到裝置並初始化 TensorFlow Lite 解釋器
若要在應用程式中使用 TensorFlow Lite 模型,請先使用 Firebase ML SDK 將最新版本的模型下載到裝置。然後,使用該模型實例化 TensorFlow Lite 解釋器。若要開始模型下載,請呼叫模型下載器的getModel()
方法,指定上傳模型時為模型指定的名稱、是否始終下載最新模型以及允許下載的條件。
您可以從三種下載行為中進行選擇:
下載類型 | 描述 |
---|---|
本地模型 | 從設備取得本地模型。如果沒有可用的本地模型,則其行為類似於LATEST_MODEL 。如果您對檢查模型更新不感興趣,請使用此下載類型。例如,您使用遠端配置來檢索模型名稱,並且始終以新名稱上傳模型(建議)。 |
LOCAL_MODEL_UPDATE_IN_BACKGROUND | 從裝置取得本機模型並開始在背景更新模型。如果沒有可用的本地模型,則其行為類似於LATEST_MODEL 。 |
最新款 | 取得最新型號。如果本機模型是最新版本,則傳回本機模型。否則,請下載最新型號。此行為將被阻止,直到下載最新版本(不建議)。僅在您明確需要最新版本的情況下才使用此行為。 |
您應該停用與模型相關的功能(例如,灰顯或隱藏部分 UI),直到您確認模型已下載。
Kotlin+KTX
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]
浮點值的圖像分類模型,則可以從Bitmap
物件產生輸入ByteBuffer
,如下例所示:
Kotlin+KTX
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
以包含模型的輸出,並將輸入緩衝區和輸出緩衝區傳遞給 TensorFlow Lite 解釋器的run()
方法。例如,對於[1 1000]
浮點值的輸出形狀:
Kotlin+KTX
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+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?
}
附錄:模型安全性
無論您如何使 TensorFlow Lite 模型可供 Firebase ML 使用,Firebase ML 都會將它們以標準序列化 protobuf 格式儲存在本機儲存中。
從理論上講,這意味著任何人都可以複製您的模型。然而,在實踐中,大多數模型都是特定於應用程式的,並且由於最佳化而變得模糊,因此風險類似於競爭對手反彙編和重複使用您的程式碼。儘管如此,在應用程式中使用自訂模型之前,您應該意識到這種風險。
在 Android API 等級 21 (Lollipop) 及更高版本上,模型將下載到自動備份中排除的目錄。
在 Android API 等級 20 及更早版本上,模型將下載到應用程式私有內部儲存中名為com.google.firebase.ml.custom.models
的目錄中。如果您使用BackupAgent
啟用檔案備份,您可以選擇排除此目錄。