如果您的應用使用自定義TensorFlow Lite模型,您可以使用 Firebase ML 來部署您的模型。通過使用 Firebase 部署模型,您可以減少應用的初始下載大小並更新應用的 ML 模型,而無需發布應用的新版本。而且,通過遠程配置和 A/B 測試,您可以動態地為不同的用戶組提供不同的模型。
TensorFlow Lite 模型
TensorFlow Lite 模型是經過優化以在移動設備上運行的 ML 模型。要獲取 TensorFlow Lite 模型:
在你開始之前
- 如果您還沒有,請將 Firebase 添加到您的 Android 項目中。
- 在您的模塊(應用級)Gradle 文件(通常為
<project>/<app-module>/build.gradle
)中,添加 Firebase ML 模型下載器 Android 庫的依賴項。我們建議使用Firebase Android BoM來控制庫版本。此外,作為設置 Firebase ML 模型下載器的一部分,您需要將 TensorFlow Lite SDK 添加到您的應用中。
Kotlin+KTX
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:32.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-ktx'
// 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 庫。
(備選)在不使用 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-ktx:24.1.2'
// Also add the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }Java
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:32.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 庫。
(備選)在不使用 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.1.2'
// 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 Admin Python 和 Node.js SDK 部署自定義 TensorFlow 模型。請參閱部署和管理自定義模型。
將自定義模型添加到 Firebase 項目後,您可以使用指定的名稱在應用中引用該模型。您可以隨時部署新的 TensorFlow Lite 模型並通過調用
getModel()
(見下文)將新模型下載到用戶的設備上。2. 將模型下載到設備並初始化一個 TensorFlow Lite 解釋器
要在應用中使用 TensorFlow Lite 模型,請先使用 Firebase ML SDK 將最新版本的模型下載到設備。然後,使用模型實例化 TensorFlow Lite 解釋器。要開始模型下載,請調用模型下載器的
getModel()
方法,指定上傳時為模型分配的名稱、是否要始終下載最新模型以及允許下載的條件。您可以從三種下載行為中進行選擇:
下載類型 描述 本地型號 從設備獲取本地模型。如果沒有可用的本地模型,則其行為類似於 LATEST_MODEL
。如果您對檢查模型更新不感興趣,請使用此下載類型。例如,您正在使用 Remote Config 檢索模型名稱,並且始終以新名稱上傳模型(推薦)。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
啟用文件備份,您可以選擇排除此目錄。除非另有註明,否則本頁面中的內容是採用創用 CC 姓名標示 4.0 授權,程式碼範例則為阿帕契 2.0 授權。詳情請參閱《Google Developers 網站政策》。Java 是 Oracle 和/或其關聯企業的註冊商標。
上次更新時間:2023-05-27 (世界標準時間)。
[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"缺少我需要的資訊" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"過於複雜/步驟過多" },{ "type": "thumb-down", "id": "outOfDate", "label":"過時" },{ "type": "thumb-down", "id": "translationIssue", "label":"翻譯問題" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"示例/程式碼問題" },{ "type": "thumb-down", "id": "otherDown", "label":"其他" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"容易理解" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"確實解決了我的問題" },{ "type": "thumb-up", "id": "otherUp", "label":"其他" }] - 在您應用的清單中,聲明需要 INTERNET 權限: