在 Apple 平台上使用自訂 TensorFlow Lite 模型

如果您的應用程式使用自訂 TensorFlow Lite 模型,則可以使用 Firebase ML 來部署模型。變更者: 可以縮減初始下載大小 應用程式及更新應用程式的機器學習模型,不必發布新版本 透過 Remote ConfigA/B Testing,您可以透過 向不同的使用者群組提供不同的模型。

事前準備

  • MLModelDownloader 程式庫僅適用於 Swift。
  • TensorFlow Lite 只能在搭載 iOS 9 以上版本的裝置上執行。

TensorFlow Lite 模型

TensorFlow Lite 模型是最佳化的機器學習模型,適合在行動裝置上執行 裝置。如要取得 TensorFlow Lite 模型,請按照下列步驟操作:

事前準備

如要搭配 Firebase 使用 TensorFlowLite,必須使用 CocoaPods 做為 TensorFlowLite 目前不支援使用 Swift Package Manager 進行安裝。詳情請參閱 CocoaPods 安裝指南 有關如何安裝「MLModelDownloader」的說明。

安裝完成後,請匯入 Firebase 和 TensorFlowLite 以便使用。

Swift

import FirebaseMLModelDownloader
import TensorFlowLite

1. 部署模型

使用 Firebase 控制台或 Firebase Admin Python 和 Node.js SDK詳情請見 部署及管理自訂模型

在 Firebase 專案中加入自訂模型後,您就能參照 在應用程式中使用您指定的名稱您隨時可以將 新的 TensorFlow Lite 模型,並將新模型下載至使用者的裝置劃分依據: 呼叫 getModel() (請見下方)。

2. 將模型下載至裝置,然後初始化 TensorFlow Lite 解譯器

如要在應用程式中使用 TensorFlow Lite 模型,請先使用 Firebase ML SDK 下載最新版本的模型到裝置。

如要開始下載模型,請呼叫模型下載工具的 getModel() 方法。 指定您在上傳模型時為模型指派的名稱 因此建議您一律下載最新模型 需要允許下載

有三種下載行為可供選擇:

下載類型 說明
localModel 取得裝置的本機模型。 如果沒有本機模型可用,這個 的運作方式與 latestModel 類似。使用這份草稿 然後下載 檢查模型更新狀態例如: 就是使用遠端設定 而且每次都會將模型上傳到 的新名稱 (建議)。
localModelUpdateInBackground 取得裝置的本機模型,並 開始在背景更新模型 如果沒有本機模型可用,這個 的運作方式與 latestModel 類似。
latestModel 取得最新模型。如果本機模型 最新版本,會傳回本機 模型否則,請下載最新版本 模型這項行為會封鎖,直到 就會下載最新版本 建議)。這個行為僅限用於 明確需要 版本。

您應該停用模型相關功能,例如 隱藏部分使用者介面,直到您確認下載模型為止。

Swift

let conditions = ModelDownloadConditions(allowsCellularAccess: false)
ModelDownloader.modelDownloader()
    .getModel(name: "your_model",
              downloadType: .localModelUpdateInBackground,
              conditions: conditions) { result in
        switch (result) {
        case .success(let customModel):
            do {
                // 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.
                let interpreter = try Interpreter(modelPath: customModel.path)
            } catch {
                // Error. Bad model file?
            }
        case .failure(let error):
            // Download was unsuccessful. Don't enable ML features.
            print(error)
        }
}

許多應用程式會在初始化程式碼中啟動下載工作,但您可以這麼做 因此在您需要使用模型前

3. 對輸入資料執行推論

取得模型的輸入和輸出形狀

TensorFlow Lite 模型解譯器會做為輸入內容並產生輸出內容 一或多個多維陣列這些陣列包含 byteintlongfloat 輕鬆分配獎金如要將資料傳遞至模型或使用其結果,請務必瞭解 模型使用的陣列數量和維度 (「形狀」)。

如果您是自行建構模型,或模型的輸入和輸出格式 您可能已有這項資訊如果不知道 模型輸入和輸出的形狀和資料類型 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] 個浮點值裡,您可能需要縮放 圖片色彩值到浮點範圍,如以下範例所示:

Swift

let image: CGImage = // Your input image
guard let context = CGContext(
  data: nil,
  width: image.width, height: image.height,
  bitsPerComponent: 8, bytesPerRow: image.width * 4,
  space: CGColorSpaceCreateDeviceRGB(),
  bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue
) else {
  return false
}

context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let imageData = context.data else { return false }

var inputData = Data()
for row in 0 ..&lt; 224 {
  for col in 0 ..&lt; 224 {
    let offset = 4 * (row * context.width + col)
    // (Ignore offset 0, the unused alpha channel)
    let red = imageData.load(fromByteOffset: offset+1, as: UInt8.self)
    let green = imageData.load(fromByteOffset: offset+2, as: UInt8.self)
    let blue = imageData.load(fromByteOffset: offset+3, as: UInt8.self)

    // Normalize channel values to [0.0, 1.0]. This requirement varies
    // by model. For example, some models might require values to be
    // normalized to the range [-1.0, 1.0] instead, and others might
    // require fixed-point values or the original bytes.
    var normalizedRed = Float32(red) / 255.0
    var normalizedGreen = Float32(green) / 255.0
    var normalizedBlue = Float32(blue) / 255.0

    // Append normalized values to Data object in RGB order.
    let elementSize = MemoryLayout.size(ofValue: normalizedRed)
    var bytes = [UInt8](repeating: 0, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedRed, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&amp;bytes, &amp;normalizedGreen, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
    memcpy(&ammp;bytes, &amp;normalizedBlue, elementSize)
    inputData.append(&amp;bytes, count: elementSize)
  }
}

然後,將輸入內容 NSData 複製到解譯器並執行:

Swift

try interpreter.allocateTensors()
try interpreter.copy(inputData, toInputAt: 0)
try interpreter.invoke()

您可以呼叫翻譯器的 output(at:) 方法,取得模型的輸出內容。 您使用輸出內容的方式取決於您使用的模型。

舉例來說,如果您接下來要進行分類 將結果的索引對應至它們代表的標籤:

Swift

let output = try interpreter.output(at: 0)
let probabilities =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: 1000)
output.data.copyBytes(to: probabilities)

guard let labelPath = Bundle.main.path(forResource: "retrained_labels", ofType: "txt") else { return }
let fileContents = try? String(contentsOfFile: labelPath)
guard let labels = fileContents?.components(separatedBy: "\n") else { return }

for i in labels.indices {
    print("\(labels[i]): \(probabilities[i])")
}

附錄:模型安全性

無論您是以何種方式將 TensorFlow Lite 模型提供給 Firebase MLFirebase ML 會以標準的序列化 protobuf 格式儲存檔案,位置在 本機儲存空間

理論上,這代表任何人都可以複製您的模型不過 實務上,大多數模型 都特別適合應用程式,並經過模糊處理 並預測其他可能與競爭對手拆解及 重複使用程式碼然而,在使用 之前,請務必先瞭解此風險 在應用程式中加入自訂模型