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:
- Użyj gotowego modelu, takiego jak oficjalny Modele TensorFlow Lite.
- Konwertuj modelu TensorFlow, Keras lub konkretnej funkcji do TensorFlow uproszczony.
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 ..< 224 {
for col in 0 ..< 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(&bytes, &normalizedRed, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&bytes, &normalizedGreen, elementSize)
inputData.append(&bytes, count: elementSize)
memcpy(&ammp;bytes, &normalizedBlue, elementSize)
inputData.append(&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.