Użyj niestandardowego modelu TensorFlow Lite na platformach Apple

Jeśli Twoja aplikacja używa niestandardowych funkcji TensorFlow Lite, możesz używać Firebase ML do wdrażania modeli. Według wdrażając modele za pomocą Firebase, możesz zmniejszyć początkowy rozmiar pobieranych danych i aktualizowanie jej modeli ML bez publikowania nowej wersji do aplikacji. Dzięki Remote Config i A/B Testing możesz dynamicznie udostępniają różne modele różnym grupom użytkowników.

Wymagania wstępne

  • Biblioteka MLModelDownloader jest dostępna tylko w języku Swift.
  • TensorFlow Lite działa tylko na urządzeniach z iOS 9 lub nowszym.

Modele TensorFlow Lite

Modele TensorFlow Lite to modele ML zoptymalizowane pod kątem uruchamiania na urządzeniach mobilnych urządzenia. Aby pobrać model TensorFlow Lite:

Zanim zaczniesz

Aby używać TensorFlowLite z Firebase, musisz używać CocoaPods jako TensorFlowLite Obecnie nie obsługuje instalacji za pomocą menedżera pakietów Swift. Zobacz Przewodnik instalacji CocoaPods na instrukcje instalacji MLModelDownloader.

Po zainstalowaniu zaimportuj Firebase i TensorFlowLite, aby z nich korzystać.

Swift

import FirebaseMLModelDownloader
import TensorFlowLite

1. Wdrażanie modelu

Wdróż niestandardowe modele TensorFlow za pomocą konsoli Firebase lub pakiety SDK Python dla administratorów Firebase i Node.js. Zobacz Wdrażanie modeli niestandardowych i zarządzanie nimi

Po dodaniu do projektu Firebase modelu niestandardowego możesz się odwoływać do w swoich aplikacjach o podanej przez Ciebie nazwie. W każdej chwili możesz wdrożyć utworzyć nowy model TensorFlow Lite i pobrać go na pliki użytkowników urządzenia według Dzwonię pod getModel() (patrz poniżej).

2. Pobierz model na urządzenie i zainicjuj interpreter TensorFlow Lite

Aby użyć modelu TensorFlow Lite w aplikacji, najpierw użyj pakietu SDK Firebase ML aby pobrać na urządzenie najnowszą wersję modelu.

Aby rozpocząć pobieranie modelu, wywołaj metodę getModel() narzędzia do pobierania modelu, określając nazwę przypisaną do modelu podczas jego przesyłania. aby zawsze pobierać najnowsze modele oraz warunki, którzy chcą zezwolić na pobieranie.

Możesz wybrać jeden z 3 sposobów pobierania:

Typ pobierania Opis
localModel Pobierz model lokalny z urządzenia. Jeśli nie jest dostępny model lokalny, działa jak latestModel. Użyj tej Jeśli Cię to nie interesuje, typ pliku do pobrania sprawdzając dostępność aktualizacji modelu. Przykład: używasz Zdalnej konfiguracji do pobierania nazwy modeli i zawsze przesłane modele pod nowymi nazwami (zalecane).
localModelUpdateInBackground Pobierz model lokalny z urządzenia zacznij aktualizować model w tle. Jeśli nie jest dostępny model lokalny, działa jak latestModel.
latestModel Pobierz najnowszy model. Jeśli model lokalny to najnowsza wersja, zwraca błąd lokalny model atrybucji. Jeśli nie, pobierz najnowszą wersję model atrybucji. To działanie będzie blokowane do czasu pobrana najnowsza wersja (nie ). Używaj tego sposobu tylko w w przypadku, gdy musisz podać najnowsze wersji.

Należy wyłączyć funkcje związane z modelem – na przykład wyszarzone lub ukryj część interfejsu użytkownika, dopóki nie potwierdzisz, że model został pobrany.

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)
        }
}

Wiele aplikacji rozpoczyna zadanie pobierania w kodzie inicjowania, ale możesz to zrobić. więc w dowolnym momencie przed użyciem modelu.

3. Przeprowadź wnioskowanie na danych wejściowych

Pobierz kształty danych wejściowych i wyjściowych modelu

Interpreter modelu TensorFlow Lite pobiera jako dane wejściowe i tworzy jako dane wyjściowe co najmniej jednej tablicy wielowymiarowej. Te tablice zawierają: byte, int, long lub float . Aby przekazywać dane do modelu lub używać jego wyników, musisz wiedzieć, liczby i wymiary („kształt”) tablic używanych przez model.

Jeśli model został utworzony przez Ciebie lub jeśli format wejściowy i wyjściowy modelu to możesz mieć już te informacje. Jeśli nie znasz kształtu i typu danych danych wejściowych i wyjściowych modelu, możesz użyć funkcji Interpreter TensorFlow Lite do sprawdzenia modelu. Przykład:

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']))

Przykładowe dane wyjściowe:

1 input(s):
[  1 224 224   3] <class 'numpy.float32'>

1 output(s):
[1 1000] <class 'numpy.float32'>

Uruchamianie tłumaczenia rozmowy

Po określeniu formatu danych wejściowych i wyjściowych modelu pobierz plik i wykonywać przekształcenia danych, które są niezbędne, aby model miał kształt właściwy.

Na przykład jeśli model przetwarza obrazy, a model ma wymiary wejściowe z [1, 224, 224, 3] wartości zmiennoprzecinkowych, konieczne może być skalowanie kolor obrazu do zakresu zmiennoprzecinkowego, jak w tym przykładzie:

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)
  }
}

Następnie skopiuj dane wejściowe NSData do tłumacza i uruchom je:

Swift

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

Dane wyjściowe modelu możesz uzyskać, wywołując metodę output(at:) interpretera. Sposób wykorzystania danych wyjściowych zależy od używanego modelu.

Jeśli na przykład przeprowadzasz klasyfikację, kolejnym krokiem może być zmapuj indeksy wyników na etykiety, które reprezentują:

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])")
}

Dodatek: zabezpieczenia modelu

Niezależnie od tego, jak udostępnisz swoje modele TensorFlow Lite Firebase ML, Firebase ML przechowuje je w standardowym zserializowanym formacie protokołu w formacie pamięci lokalnej.

Teoretycznie oznacza to, że każdy może skopiować Twój model. Pamiętaj jednak: W praktyce większość modeli jest specyficzna dla danej aplikacji i pod kątem podobnych optymalizacji, jakie stwarzają konkurencji, demontaż ponownego wykorzystania kodu. Musisz jednak wiedzieć o tym ryzyku, zanim zaczniesz niestandardowy model w swojej aplikacji.