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 ML aplikacji bez wydawania nowej wersji aplikacji. A dzięki zdalnej konfiguracji i testom A/B możesz dynamicznie udostępniać 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 .
- W pliku Gradle modułu (na poziomie aplikacji) (zwykle
<project>/<app-module>/build.gradle.kts
lub<project>/<app-module>/build.gradle
) dodaj zależność dla Firebase ML biblioteka Android do pobierania modeli. Zalecamy używanie Firebase Android BoM do kontrolowania wersji bibliotek.Ponadto w ramach konfigurowania narzędzia do pobierania modeli Firebase ML musisz dodać do swojej aplikacji zestaw SDK TensorFlow Lite.
Kotlin+KTX
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:32.3.1")) // 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") }Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze korzystać ze zgodnych wersji bibliotek Firebase Android.
(Alternatywnie) Dodaj zależności biblioteki Firebase bez korzystania z BoM
Jeśli zdecydujesz się nie używać BoM Firebase, musisz określić każdą wersję biblioteki Firebase w jej wierszu zależności.
Pamiętaj, że jeśli używasz w swojej aplikacji wielu bibliotek Firebase, zdecydowanie zalecamy korzystanie z BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.
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.3")
// 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.3.1")) // 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") }Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze korzystać ze zgodnych wersji bibliotek Firebase Android.
(Alternatywnie) Dodaj zależności biblioteki Firebase bez korzystania z BoM
Jeśli zdecydujesz się nie używać BoM Firebase, musisz określić każdą wersję biblioteki Firebase w jej wierszu zależności.
Pamiętaj, że jeśli używasz w swojej aplikacji wielu bibliotek Firebase, zdecydowanie zalecamy korzystanie z BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.
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.3")
// Also add the dependency for the TensorFlow Lite library and specify its version implementation("org.tensorflow:tensorflow-lite:2.3.0") }- W manifeście swojej aplikacji zadeklaruj, że wymagane jest uprawnienie INTERNET:
<uses-permission android:name="android.permission.INTERNET" />
1. Wdróż swój model
Wdrażaj niestandardowe modele TensorFlow przy użyciu konsoli Firebase lub zestawów SDK Firebase Admin Python i Node.js. 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 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 funkcję
getModel()
(patrz poniżej).2. Pobierz model na urządzenie i zainicjuj interpreter TensorFlow Lite
Aby użyć swojego modelu TensorFlow Lite w swojej aplikacji, najpierw użyj 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()
narzędzia do pobierania modeli, określając nazwę, którą przypisałeś modelowi podczas przesyłania, czy chcesz zawsze pobierać najnowszy model, oraz warunki, na jakich chcesz zezwolić na pobieranie.Możesz wybrać jeden z trzech sposobów pobierania:
Pobierz typ Opis LOKALNY_MODEL Pobierz model lokalny z urządzenia. Jeśli nie ma dostępnego modelu lokalnego, zachowuje się jak LATEST_MODEL
. Użyj tego typu pobierania, jeśli nie chcesz sprawdzać dostępności 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 rozpocznij aktualizację modelu w tle. Jeśli nie ma dostępnego modelu lokalnego, zachowuje się jak LATEST_MODEL
.NAJNOWSZY MODEL Pobierz najnowszy model. Jeśli model lokalny jest najnowszą wersją, zwraca model lokalny. W przeciwnym razie pobierz najnowszy model. To zachowanie będzie blokować do momentu pobrania najnowszej wersji (niezalecane). Użyj tego zachowania tylko w przypadkach, gdy wyraźnie potrzebujesz najnowszej wersji. Należy wyłączyć funkcje związane z modelem — na przykład wyszarzenie lub ukrycie części interfejsu użytkownika — do czasu potwierdzenia, że model został pobrany.
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); } } });
Wiele aplikacji uruchamia zadanie pobierania w swoim kodzie inicjującym, ale możesz to zrobić w dowolnym momencie, zanim będzie trzeba użyć modelu.
3. Wykonaj wnioskowanie na danych wejściowych
Uzyskaj wejściowe i wyjściowe kształty swojego modelu
Interpreter modelu TensorFlow Lite pobiera 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 użyć jego wyniku, musisz znać liczbę i wymiary („kształt”) tablic używanych w modelu.Jeśli sam zbudowałeś model lub jeśli format danych wejściowych i wyjściowych modelu jest udokumentowany, być może masz już te informacje. Jeśli nie znasz kształtu i typu danych danych wejściowych i wyjściowych swojego 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 wyjście:
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 przeprowadź na nich wszelkie przekształcenia, które są niezbędne do uzyskania danych wejściowych o odpowiednim kształcie dla Twojego modelu.Na przykład, jeśli masz model klasyfikacji obrazów z kształtem wejściowym
[1 224 224 3]
wartości zmiennoprzecinkowych, możesz wygenerować wejściowyByteBuffer
z obiektuBitmap
, jak pokazano w poniższym przykładzie: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); } }
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: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);
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 na etykiety, które reprezentują:
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? }
Dodatek: Bezpieczeństwo modeli
Niezależnie od tego, w jaki sposób udostępniasz swoje modele TensorFlow Lite w Firebase ML, Firebase ML przechowuje je w standardowym, serializowanym formacie protobuf w pamięci lokalnej.
Teoretycznie 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 ryzyka dezasemblacji i ponownego użycia kodu przez konkurencję. Niemniej jednak powinieneś być świadomy tego ryzyka, zanim użyjesz niestandardowego modelu w swojej aplikacji.
W interfejsie API systemu Android na poziomie 21 (Lollipop) i nowszych model jest pobierany do katalogu wykluczonego z automatycznej kopii zapasowej .
W interfejsie API Androida na poziomie 20 lub starszym 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 zapasowych plików za pomocąBackupAgent
, można wykluczyć ten katalog.O ile nie stwierdzono inaczej, treść tej strony jest objęta licencją Creative Commons – uznanie autorstwa 4.0, a fragmenty kodu są dostępne na licencji Apache 2.0. Szczegółowe informacje na ten temat zawierają zasady dotyczące witryny Google Developers. Java jest zastrzeżonym znakiem towarowym firmy Oracle i jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2023-09-26 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 swojej aplikacji zadeklaruj, że wymagane jest uprawnienie INTERNET: