Jeśli Twoja aplikacja korzysta z niestandardowych modeli TensorFlow Lite , możesz użyć Firebase ML do wdrożenia swoich modeli. Wdrażając modele za pomocą Firebase, możesz zmniejszyć początkowy rozmiar pobieranej aplikacji i zaktualizować modele uczenia maszynowego aplikacji bez wydawania nowej wersji aplikacji. A dzięki zdalnej konfiguracji i testom A/B możesz dynamicznie obsługiwać różne modele różnym grupom użytkowników.
Modele TensorFlow Lite
Modele TensorFlow Lite to modele ML zoptymalizowane do działania na urządzeniach mobilnych. Aby uzyskać model TensorFlow Lite:
- Użyj gotowego modelu, takiego jak jeden z oficjalnych modeli TensorFlow Lite .
- Konwertuj model TensorFlow, model Keras lub konkretną funkcję na TensorFlow Lite.
Zanim zaczniesz
- Jeśli jeszcze tego nie zrobiłeś, dodaj Firebase do swojego projektu na Androida .
- Korzystając z Firebase Android BoM , zadeklaruj zależność dla biblioteki systemu Android narzędzia do pobierania modelu Firebase ML w pliku Gradle modułu (na poziomie aplikacji) (zwykle
app/build.gradle
).Ponadto w ramach konfigurowania narzędzia do pobierania modeli Firebase ML musisz dodać do swojej aplikacji pakiet TensorFlow Lite SDK.
Java
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:30.2.0') // Declare 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 declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze używać zgodnych wersji bibliotek Firebase Android.
(Alternatywnie) Zadeklaruj zależności biblioteki Firebase bez użycia BoM
Jeśli zdecydujesz się nie korzystać z BoM Firebase, musisz określić każdą wersję biblioteki Firebase w jej wierszu zależności.
Pamiętaj, że jeśli korzystasz z wielu bibliotek Firebase w swojej aplikacji, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.
dependencies { // Declare 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.0.3'
// Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }Kotlin+KTX
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:30.2.0') // Declare 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 declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze używać zgodnych wersji bibliotek Firebase Android.
(Alternatywnie) Zadeklaruj zależności biblioteki Firebase bez użycia BoM
Jeśli zdecydujesz się nie korzystać z BoM Firebase, musisz określić każdą wersję biblioteki Firebase w jej wierszu zależności.
Pamiętaj, że jeśli korzystasz z wielu bibliotek Firebase w swojej aplikacji, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.
dependencies { // Declare 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.0.3'
// Also declare the dependency for the TensorFlow Lite library and specify its version implementation 'org.tensorflow:tensorflow-lite:2.3.0' }- W manifeście aplikacji zadeklaruj, że wymagane jest uprawnienie INTERNET:
<uses-permission android:name="android.permission.INTERNET" />
1. Wdróż swój model
Wdrażaj niestandardowe modele TensorFlow za pomocą konsoli Firebase lub pakietów Firebase Admin Python i Node.js SDK. Zobacz Wdrażanie modeli niestandardowych i zarządzanie nimi .
Po dodaniu niestandardowego modelu do projektu Firebase możesz odwoływać się do modelu w swoich aplikacjach, używając określonej przez siebie nazwy. W dowolnym momencie możesz wdrożyć nowy model TensorFlow Lite i pobrać nowy model na urządzenia użytkowników, wywołując
getModel()
(patrz poniżej).2. Pobierz model na urządzenie i zainicjuj interpreter TensorFlow Lite
Aby użyć modelu TensorFlow Lite w swojej aplikacji, najpierw użyj pakietu Firebase ML SDK, aby pobrać najnowszą wersję modelu na urządzenie. Następnie utwórz instancję interpretera TensorFlow Lite z modelem.Aby rozpocząć pobieranie modelu, wywołaj metodę
getModel()
programu do pobierania modeli, określając nazwę przypisaną modelowi podczas jego przesyłania, czy chcesz zawsze pobierać najnowszy model oraz warunki, na jakich chcesz zezwolić na pobieranie.Możesz wybrać spośród trzech zachowań pobierania:
Typ pobierania Opis LOCAL_MODEL Pobierz model lokalny z urządzenia. Jeśli nie ma dostępnego modelu lokalnego, działa to jak LATEST_MODEL
. Użyj tego typu pobierania, jeśli nie chcesz sprawdzać aktualizacji modelu. Na przykład używasz Zdalnej konfiguracji do pobierania nazw modeli i zawsze przesyłasz modele pod nowymi nazwami (zalecane).LOCAL_MODEL_UPDATE_IN_BACKGROUND Pobierz model lokalny z urządzenia i zacznij aktualizować model w tle. Jeśli nie ma dostępnego modelu lokalnego, działa to jak LATEST_MODEL
.NAJNOWSZY MODEL Pobierz najnowszy model. Jeśli model lokalny to najnowsza wersja, zwraca model lokalny. W przeciwnym razie pobierz najnowszy model. To zachowanie będzie blokowane do momentu pobrania najnowszej wersji (niezalecane). Użyj tego zachowania tylko w przypadkach, w których wyraźnie potrzebujesz najnowszej wersji. Należy wyłączyć funkcje związane z modelem — na przykład wyszarzanie lub ukrywanie części interfejsu użytkownika — dopóki nie potwierdzisz, że model został pobrany.
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); } } });
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) } }
Wiele aplikacji rozpoczyna zadanie pobierania w swoim kodzie inicjującym, ale możesz to zrobić w dowolnym momencie, zanim będziesz musiał użyć modelu.
3. Wykonaj wnioskowanie na danych wejściowych
Uzyskaj kształty wejściowe i wyjściowe swojego modelu
Interpreter modelu TensorFlow Lite przyjmuje jako dane wejściowe i generuje jako dane wyjściowe jedną lub więcej tablic wielowymiarowych. Te tablice zawierają wartości
byte
,int
,long
lubfloat
. Zanim będziesz mógł przekazać dane do modelu lub wykorzystać jego wynik, musisz znać liczbę i wymiary ("kształt") tablic używanych przez Twój model.Jeśli sam zbudowałeś model lub jeśli format danych wejściowych i wyjściowych modelu jest udokumentowany, możesz już mieć te informacje. Jeśli nie znasz kształtu i typu danych danych wejściowych i wyjściowych modelu, możesz użyć interpretera TensorFlow Lite do sprawdzenia modelu. Na przykład:
Pyton
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'>
Uruchom tłumacza
Po określeniu formatu danych wejściowych i wyjściowych modelu pobierz dane wejściowe i wykonaj na nich wszelkie przekształcenia, które są niezbędne do uzyskania danych wejściowych o odpowiednim kształcie dla modelu.Na przykład, jeśli masz model klasyfikacji obrazów z kształtem wejściowym wartości zmiennoprzecinkowych
[1 224 224 3]
, możesz wygenerować wejściowyByteBuffer
z obiektuBitmap
, jak pokazano w poniższym przykładzie: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); } }
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) } }
Następnie przydziel
ByteBuffer
wystarczająco duży, aby pomieścić dane wyjściowe modelu i przekaż bufor wejściowy i wyjściowy do metodyrun()
interpretera TensorFlow Lite. Na przykład dla kształtu wyjściowego[1 1000]
wartości zmiennoprzecinkowych: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
val bufferSize = 1000 * java.lang.Float.SIZE / java.lang.Byte.SIZE val modelOutput = ByteBuffer.allocateDirect(bufferSize).order(ByteOrder.nativeOrder()) interpreter?.run(input, modelOutput)
Sposób wykorzystania danych wyjściowych zależy od używanego modelu.
Na przykład, jeśli przeprowadzasz klasyfikację, w następnym kroku możesz zmapować indeksy wyniku do etykiet, które reprezentują:
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? }
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? }
Załącznik: Zabezpieczenia modelu
Niezależnie od tego, w jaki sposób udostępniasz modele TensorFlow Lite w Firebase ML, Firebase ML przechowuje je w standardowym serializowanym formacie protobuf w pamięci lokalnej.
W teorii oznacza to, że każdy może skopiować Twój model. Jednak w praktyce większość modeli jest tak specyficzna dla aplikacji i zaciemniona przez optymalizacje, że ryzyko jest podobne do tego, jakie ma konkurencja w przypadku demontażu i ponownego użycia kodu. Niemniej jednak powinieneś być świadomy tego ryzyka, zanim użyjesz niestandardowego modelu w swojej aplikacji.
Na poziomie 21 interfejsu API systemu Android (Lollipop) i nowszych model jest pobierany do katalogu wykluczonego z automatycznego tworzenia kopii zapasowych .
W przypadku interfejsu API systemu Android na poziomie 20 i starszych model jest pobierany do katalogu o nazwie
com.google.firebase.ml.custom.models
w prywatnej pamięci wewnętrznej aplikacji. Jeśli włączono tworzenie kopii zapasowej plików za pomocąBackupAgent
, możesz wykluczyć ten katalog.Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2022-07-06 UTC.
[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Brak potrzebnych mi informacji" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Zbyt skomplikowane / zbyt wiele czynności do wykonania" },{ "type": "thumb-down", "id": "outOfDate", "label":"Nieaktualne treści" },{ "type": "thumb-down", "id": "translationIssue", "label":"Problem z tłumaczeniem" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Problem z przykładami/kodem" },{ "type": "thumb-down", "id": "otherDown", "label":"Inne" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Łatwo zrozumieć" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Rozwiązało to mój problem" },{ "type": "thumb-up", "id": "otherUp", "label":"Inne" }] - W manifeście aplikacji zadeklaruj, że wymagane jest uprawnienie INTERNET: