Inteligentne aplikacje

Opanowanie funkcji AI na urządzeniu dzięki ML Kit i LiteRT w Usługach Google Play

Głośniki

  • Chintan Parikh

    Lead Product Manager

  • Fergus Henderson

    Inżynier oprogramowania

Informacje

Informacje o wystąpieniu

Nie musisz już wybierać między wygodą gotowej AI a elastycznością niestandardowego modelu – możesz wdrożyć oba te rozwiązania w jednej, bardzo prostej aplikacji bez dodawania megabajtów niepotrzebnych danych binarnych.

Podczas tej sesji pokażemy, jak utworzyć taką architekturę dual-stack w jednej aplikacji na Androida. Dowiesz się, jak wykorzystać ML Kit do gotowych klasycznych zadań ML (takich jak skanowanie dokumentów) oraz LiteRT w Usługach Play do niestandardowych zadań związanych z rozpoznawaniem obrazów lub dźwiękiem. Szczegółowo omówimy, jak obie ścieżki implementacji łączą się, aby wykorzystać nowoczesne środowisko wykonawcze LiteRT, zapewniając aplikacji płynne działanie z akceleracją sprzętową na procesorach i GPU przy praktycznie zerowym rozmiarze pobierania.

Najważniejsze wnioski dla deweloperów:

– Bezkompromisowa wydajność: zarówno gotowe, jak i niestandardowe modele są automatycznie akcelerowane sprzętowo za pomocą ujednoliconego interfejsu CompiledModel API.

– Mikropliki APK: znacznie zmniejsz rozmiar pobieranej aplikacji, przenosząc środowiska wykonawcze ML Kit i LiteRT do usług Google Play.

– Integracja hybrydowa: opanuj uruchamianie wielu przepływów pracy ML obok siebie w środowisku produkcyjnym bez konfliktów zasobów.

Podsumowanie

  • LiteRT w usługach Google Play udostępnia jedno środowisko wykonawcze w aplikacjach, co pozwala zmniejszyć rozmiar plików APK o około 8 MB.
  • Gotowe funkcje ML Kit i niestandardowe modele LiteRT mogą działać razem w jednej aplikacji w tym samym środowisku wykonawczym.
  • Interfejs CompiledModel API upraszcza akcelerację GPU i zapewnia nawet 1,4 raza większą wydajność niż starsze wnioskowanie GPU TFLite.
  • Platforma jest dostępna nie tylko na telefonach, ale też na Wear OS 4 lub nowszym oraz systemie operacyjnym Android Automotive na Androidzie 11 lub nowszym.
  • Wdrożenie LiteRT w usługach Google Play obejmuje zaktualizowanie zależności Maven do play-services-litert, wywołanie LiteRt.initialize w celu uzyskania środowiska i przekazanie go do CompiledModel.create.
  • Zalecamy przejście na interfejs CompiledModel API w wersji 2.x, ponieważ wersja 1.x jest w trybie konserwacji, a NNAPI zostanie wycofany.

Umiejętności

Zasoby

Gemini Notebook

Tematy

  • on-device-ai
  • ml-kit
  • litert
  • google-play-services
  • akceleracja-gpu
  • uczenie maszynowe

Transkrypcja

Pobierz transkrypcję

Wprowadzenie do LiteRT i omówienie tej usługi

  • Dobry wieczór.

  • Zaraz zaczynamy.

  • Dlatego gdy obecnie mówi się o „AI na urządzeniu”, często ma się na myśli duże modele językowe.

  • Wcześniej dzisiaj odbyło się kilka prelekcji na temat Gemini Nano, które zostały omówione w ML Kit, Firebase i wielu innych usługach Google.

  • Ta sesja dotyczy drugiej połowy: klasycznego uczenia maszynowego i modelu, który przynosisz ze sobą.

  • Prawdopodobnie zdarzyło Ci się już dzisiaj skorzystać z niej kilka razy, nawet o tym nie wiedząc.

  • Zastanów się, czy używasz aplikacji, w których rozmywasz tło, używasz skanera kodów kreskowych lub edytujesz obrazy.

  • Wiele z nich opiera się na klasycznym uczeniu maszynowym i zwykle działa na urządzeniu.

  • Jeśli kiedykolwiek dodawaliście którąś z tych funkcji do własnej aplikacji lub pakietu APK, często musieliście wybierać między gotowym interfejsem API a własnym modelem.

  • Jak wpłynie to na rozmiar aplikacji?

  • Dzisiaj przekonacie się, że nie musicie wybierać między gotowym rozwiązaniem a własnym modelem.

  • Możesz zrobić obie te rzeczy za pomocą jednego środowiska wykonawczego.

  • Nazywam się Chintan Parikh.

  • Jestem menedżerem produktu LiteRT, a ze mną jest Fergus, kierownik techniczny ds. usług ML na Androidzie.

  • Cześć.

  • Na koniec dowiesz się, jak utworzyć jedną aplikację, która uruchamia 2 modele na każdej klatce z kamery z szybkością około 30 klatek na sekundę.

  • Ta prezentacja składa się z 4 części.

  • W pierwszej części omówimy rozwiązania Google AI na urządzeniu, skupiając się na klasycznych systemach uczących się, czyli ML Kit i LiteRT.

  • Następnie omówimy nowości w LiteRT i usługach Google Play.

  • Omówimy też nowy interfejs API CompiledModel z LiteRT i obsługiwane przez nas urządzenia.

  • Po trzecie, pokażemy Ci, jak utworzyć nową aplikację.

  • Fergus omówi tworzenie aplikacji za pomocą ML Kit i niestandardowego modelu w jednym pliku APK.

  • Na koniec pokażemy, jak uaktualnić istniejącą aplikację za pomocą trybu agenta.

  • Możesz też utworzyć szkielet nowej aplikacji przy pomocy tego agenta.

  • OK.

  • Zacznijmy od tego, czym jest LiteRT.

  • LiteRT to środowisko wykonawcze Google do wnioskowania na urządzeniu dla Twoich modeli.

  • Używa tego samego formatu pliku .tflite, który był używany wcześniej w TensorFlow Lite.

  • Został on przeprojektowany pod kątem wydajności i obsługuje wiele platform.

  • Oznacza to, że możesz importować modele z PyTorch, TensorFlow, a nawet JAX, aby przekonwertować je na format FlatBuffer dla LiteRT.

  • Od 2022 roku TensorFlow Lite w usługach Google Play jest oficjalnym środowiskiem wykonawczym Androida na urządzeniu dla modeli niestandardowych.

  • Dzisiaj wprowadzamy dużą aktualizację, o której będziemy dużo mówić.

  • Uaktualnienie wprowadzi najnowszy interfejs API LiteRT CompiledModel, w tym nowe, ulepszone wnioskowanie GPU, które będzie 1,4 raza szybsze, a także umożliwi tworzenie mniejszych aplikacji o znacznie mniejszych rozmiarach plików APK.

  • Dlaczego więc udostępniamy ją przez Usługi Google Play?

  • Jest kilka zalet, a rozmiar aplikacji i rozdęte pliki APK to zdecydowanie duży problem, o którym słyszę w wielu rozmowach. To prawdziwe wyzwanie, prawda?

  • Dzięki temu środowisko wykonawcze jest niewielkie.

  • Środowisko wykonawcze nie znajduje się w pliku APK, więc korzystasz z cienkiego klienta, co zmniejsza rozmiar pliku APK o około 8 MB.

  • Druga korzyść to skuteczność.

  • Masz jedną kopię środowiska wykonawczego, więc środowisko wykonawcze LiteRT jest udostępniane wszystkim aplikacjom.

  • Jeśli masz wiele aplikacji, każda z nich może zaoszczędzić 8 MB.

  • To bardzo dużo, gdy próbujesz zaoszczędzić miejsce na dysku i mieć mniejszą aplikację.

  • Po drugie, jest utrzymywany.

  • Google dostarcza poprawki błędów, rozwiązuje problemy ze sterownikami GPU, których nie musisz rozwiązywać, a wszelkie inne aktualizacje zabezpieczeń są dostarczane w ramach automatycznych aktualizacji.

  • Jak już wspominałem, GPU jest szybszy – 1,4 raza szybszy.O tym też opowiem bardziej szczegółowo.

  • Jeśli chodzi o zasięg, możemy wysyłać wiadomości na starsze urządzenia z Androidem.

  • LiteRT w usługach Google Play obsługuje urządzenia z Androidem 7 z 2016 r.

  • Fergus pokaże też inne nowe urządzenia, na które rozszerzamy naszą ofertę.

  • To jest pojazd dostawczy, a teraz porozmawiajmy o następnym kroku, czyli środowisku wykonawczym.

  • LiteRT nie jest więc nowym ani eksperymentalnym rozwiązaniem.

  • TensorFlow Lite i LiteRT działają już w ponad 250 tys. aplikacji.

  • Obecnie działa na ponad 3,8 miliarda urządzeń.

  • Wiele aplikacji, których używasz, może działać na tej platformie, nawet jeśli o tym nie wiesz.

  • To oznacza też ponad bilion wnioskowań dziennie, prawda?

  • Przy tej skali z pewnością napotkaliśmy każdy możliwy problem z chipsetem, udało nam się rozwiązać problemy z pamięcią ROM i sterownikami GPU, a teraz mamy dla Ciebie rozwiązanie.

  • LiteRT jest również używany przez Google w flagowych aplikacjach, na różnych platformach, a nawet na kilku urządzeniach.

  • Efekty w YouTube Shorts, segmentacja tła w Meet czy usuwanie rozmycia to tylko niektóre przykłady, w których filmy w czasie rzeczywistym i ciężkie modele do generowania obrazów działają na LiteRT.

  • To również bardzo ważne, ponieważ szybkie i angażujące użytkowników przypadki użycia stają się niezwykle istotne.

  • Jest to więc to samo środowisko wykonawcze, które wzmocniliśmy na potrzeby tych flagowych funkcji, i to właśnie otrzymujesz dzięki Usługom Google Play.

Dlaczego warto uruchamiać AI na urządzeniu

  • Omówmy też, dlaczego warto korzystać z AI na urządzeniu.

  • Jeśli zależy Ci na krótkim czasie oczekiwania, prywatności, pracy offline lub niskich kosztach, uruchom model offline.

  • Może być ich więcej, ale te są najbardziej oczywiste i najczęściej wymieniane w kontekście działania na urządzeniu.

  • Uruchamianie na urządzeniu nie zawsze jest bezpłatne.

  • Ma ono pewne niuanse i wyzwania.

  • Omówimy też niektóre z tych wyzwań i pokażemy, jak sobie z nimi poradzić.

  • Wydajność: jak widzieliście w niektórych przykładach z poprzednich aplikacji, budżety na opóźnienia i pamięć są zawsze napięte.

  • Wideo i audio w czasie rzeczywistym wymagają najwyższej wydajności.

  • Nawet proste funkcje interaktywne muszą działać szybko.

  • W przeciwnym razie stracisz zaangażowanie użytkowników.

  • Różnorodność sprzętu: istnieją setki układów SoC z różnymi konfiguracjami procesorów i GPU.

  • Nie możesz napisać kodu dla wszystkich tych przypadków, prawda?

  • Jak sobie z tym poradzić?

  • Rozmiar pliku APK: dołączenie środowiska wykonawczego zwiększa rozmiar każdego pobrania, co może mieć wpływ na współczynniki konwersji.

  • Dostosowywanie: trenowanie modelu, jakość, rozmiar modelu – wszystkie te kwestie są niezwykle ważne jeszcze przed wdrożeniem.

  • Tak, stworzenie świetnej aplikacji na urządzenie może być trudne.

  • W każdej z tych sytuacji chcemy, aby platforma wykonywała pracę za Ciebie, a nie na odwrót, prawda?

  • Oferta Google dotycząca urządzeń powstała, aby sprostać tym wyzwaniom. Omówimy ją w następnej kolejności.

  • Skupimy się dziś na 2 prostych rozwiązaniach.

  • Istnieją 2 proste sposoby dodawania AI na urządzeniu za pomocą Usług Google Play.

  • Ścieżka 1 to gotowa ścieżka z użyciem ML Kit, prawda?

  • Są to gotowe do użycia interfejsy API do rozpoznawania obrazów i języka, które wymagają ograniczonej wiedzy z zakresu uczenia maszynowego. Dostępnych jest wiele modeli, które są dostarczane przez Usługi Google Play.

  • Na kolejnych slajdach omówimy kilka przykładów.

  • Ścieżka niestandardowa, która jest realizowana przez LiteRT.

  • LiteRT umożliwia korzystanie z własnego modelu i uruchamianie go na procesorze lub GPU.

  • Środowisko wykonawcze również pochodzi z Usług Google Play.

  • Nie musisz więc umieszczać go w pliku APK.

  • Te opcje nie wykluczają się wzajemnie.

  • Można też zawsze połączyć je w pary.

  • I właśnie to stworzymy dzisiaj w ciągu kilku minut.

  • Najpierw jednak omówmy, co obejmuje ML Kit.

  • Oto co ML Kit oferuje od razu po zainstalowaniu.

  • Jeśli więc uważasz, że niektóre z tych funkcji spełniają Twoje potrzeby, to świetny punkt wyjścia i masz już przewagę.

  • Mamy funkcje rozpoznawania obrazów, kodów kreskowych, dokumentów, tekstu, pozycji i wiele innych, interfejsy API do obsługi języków, takie jak tłumaczenie, inteligentne odpowiedzi, a nawet wyodrębnianie encji.

  • Najważniejsze jest to, że wiele z tych interfejsów API do rozpoznawania obrazów i języka działa z LiteRT.

  • Jeśli więc ML Kit spełnia Twoje potrzeby, możesz zacząć od niego.

  • A gdy nie jest, możesz użyć własnego modelu.

  • I tu dochodzimy do kluczowej kwestii: ML Kit i Twój model niestandardowy nie będą 2 środowiskami wykonawczymi, jak już wspomniałem.

  • Można je traktować jako 2 drzwi wejściowe prowadzące do tego samego LiteRT, który będzie działać pod maską.

  • LiteRT będzie więc środowiskiem wykonawczym, które będzie koordynować obie te funkcje.

  • Jeśli więc Twoja aplikacja korzysta już ze Sklepu Play, możesz użyć ML Kit.

  • W przeciwnym razie omówimy też ścieżkę LiteRT.

Co nowego w LiteRT

  • Omówmy też nowości w LiteRT.

  • Jak już wspomnieliśmy, LiteRT to rozwinięcie TensorFlow Lite.

  • Największe ulepszenia to szybszy GPU.

  • Szybszy procesor graficzny obsługuje OpenCL, OpenGL, a także zapewnia obsługę wielu platform, nawet w przypadku backendów Metal.

  • Możesz więc używać tego rozwiązania na wielu platformach, jeśli jest taka potrzeba.

  • Jest też prostsza.

  • Mamy jeden ujednolicony przepływ pracy na potrzeby akceleracji CPU, GPU i NPU.

  • Procesory i GPU są obecnie dostępne w usługach Google Play, natomiast NPU jest obecnie dołączony do LiteRT i nadal nad nim pracujemy.

  • Wcześniej każdy akcelerator wymagał innej konfiguracji delegata, prawda?

  • Wystarczy to zrobić tylko raz.

  • Dzięki temu istnieje jeden interfejs API z automatycznym przełączaniem na procesor i nie trzeba konfigurować dedykowanych delegatów.

  • Możesz po prostu użyć wywołań akceleratora, które mogą zarządzać tym znacznie prościej i przy użyciu mniejszej ilości kodu.

  • Jest też bardzo wydajny – ten sam model działa na wielu platformach, jak już wspominałem.

  • Elastyczność będzie miała kluczowe znaczenie.

  • Format .tflite pozostaje więc taki sam.

  • Jeśli masz już aplikację, nadal możesz używać tego formatu.

  • Jeśli tworzysz nową aplikację, możesz ponownie użyć tego formatu pliku.

  • Co ciekawe, obsługujemy też interfejs Interpreter API, który wcześniej był dostępny w TensorFlow Lite.

  • Jeśli więc chcesz przeprowadzić migrację etapami, interfejs Interpreter API jest dołączony do nowego LiteRT, co ułatwia migrację.

  • To jest środowisko wykonawcze.

  • Porozmawiajmy o tym, co można dzięki temu stworzyć.

  • Oto co obecnie tworzą deweloperzy aplikacji na Androida.

  • Wszystko – od efektów aparatu, edycji zdjęć, inteligentnego pisania po gry i awatary, prawda?

  • Wiele z tych aplikacji będzie wymagać funkcji działających w czasie rzeczywistym.

  • GPU wysyła klatki bezpośrednio z aparatu, więc ważne jest, aby wszystko działało szybko i w czasie rzeczywistym.

  • Niektóre z tych modeli do edycji zdjęć również stają się coraz bardziej wymagające.

  • To samo dotyczy funkcji AR/VR, które widzieliście w niektórych wersjach demonstracyjnych z okularami. Wiele z nich działa na bazie LiteRT.

  • To samo środowisko wykonawcze, które obsługuje teraz flagowe funkcje Google, a także usługi Google Play, dzięki czemu masz dostęp do wszystkich tych funkcji bez konieczności dołączania czegokolwiek do pakietu APK.

  • Teraz utwórzmy aplikację. Fergus pokaże nam, jak to zrobić.

  • Zróbmy to.

  • Dziękuję, Chintan.

  • Opowiem trochę o nowościach w LiteRT w usługach Google Play.

  • Zanim zaczniemy tworzyć, jeszcze jedna informacja: wszystko, co właśnie widzieliście, działa teraz nie tylko na telefonie. LiteRT w usługach Google Play jest też dostępny na Wear OS i systemie operacyjnym Android Automotive.

  • Możesz więc mieć modele działające na urządzeniu na zegarku lub innym urządzeniu do noszenia albo w samochodzie.

  • Wcześniej można było używać aplikacji na telefonie, która była aplikacją towarzyszącą dla Wear, ale teraz można ją uruchomić na samym urządzeniu do noszenia. To samo dotyczy Androida Automotive.

  • Dzięki temu masz ten sam interfejs API i ten sam model .tflite, ale więcej platform.

  • Nie musisz tworzyć osobnej implementacji dla każdego formatu – możesz użyć tej samej implementacji na wszystkich tych urządzeniach.

  • Piękno modelu dystrybucji usług Google Play polega na tym, że możemy przenieść tę funkcję na starsze urządzenia.

  • W przypadku systemu operacyjnego Android Automotive obsługujemy wersje od Androida 11 wydanego w 2020 r., a w przypadku Wear OS – od Wear OS 4.

  • OK.

  • Teraz omówię 2 różne ścieżki: tworzenie nowej aplikacji i uaktualnianie istniejącej.

  • To wszystko, co chcieliśmy omówić w tej prezentacji.

  • Zacznę od przykładowej aplikacji, która łączy użycie ML Kit z niestandardowym modelem GPU działającym na LiteRT.

  • W przypadku uaktualniania istniejącej aplikacji trzeba będzie wprowadzić 3 niewielkie zmiany: zmianę w Gradle, aby zaktualizować zależności, zmianę w init, aby włączyć LiteRT w Usługach Google Play, oraz przejście z interfejsu Interpreter API na interfejs CompiledModel API.

  • Zaczniemy jednak od nowej aplikacji, ponieważ przejście na nią ma o wiele więcej sensu, gdy zobaczysz, co zyskujesz.

Omówienie przykładowej aplikacji

  • Tworzymy więc nową aplikację.

  • Oto aplikacja, którą utworzymy.

  • Będzie to widok z kamery na żywo, w którym Ty będziesz ostry, a tło będzie miało artystyczny styl.

  • Zaczniemy od kadru.

  • Obrazy z kadru aparatu będziemy przesyłać strumieniowo przez segmentację selfie w pakiecie ML Kit.

  • To jeden z istniejących gotowych interfejsów API ML Kit.

  • W ten sposób powstanie maska pierwszego planu, która w zasadzie określi, które piksele na obrazie odpowiadają osobie na obrazie.

  • Następnie weźmiemy nasz model niestandardowy, który jest modelem typu przeniesienie stylu, i zastosujemy styl do obrazu.

  • Zastosujemy go do całej klatki, ale tak naprawdę interesuje nas tylko tło, ponieważ na koniec weźmiemy oryginalną klatkę, maskę i tło ze stylem i połączymy je za pomocą prostej logiki, aby uzyskać klatkę, w której zachowaliśmy obiekt, a tło ma styl.

  • Dlatego chcemy mieć Korzystamy z gotowych interfejsów API, jeśli są dostępne, i niestandardowych interfejsów API, jeśli wyróżniają naszą aplikację.

  • To jest pierwsza część, w której wywołujemy interfejs API ML Kit do segmentacji selfie.

    // 1. Configure and create segmenter client
    val segmenter = Segmentation.getClient(
        SelfieSegmenterOptions.Builder()
            .setDetectorMode(
                SelfieSegmenterOptions.STREAM_MODE)
            .build())
    
    // 2. Prepare image & run inference
    fun processFrame(mediaImage: Image) {
      val image = InputImage.fromMediaImage(
          mediaImage, /* rotationDegrees= */ 0)
      segmenter.process(image)
          .addOnSuccessListener { mask -> … }
    }
  • Czyli to jest jak zwykły interfejs API, prawda?

  • To jest podstawowa wiedza dla deweloperów aplikacji na Androida.

  • Wystarczy, że zajrzysz do dokumentacji interfejsu API lub poprosisz Gemini o stworzenie kodu.

  • Ale jest to dość proste.

  • Podczas tworzenia klienta przekazujesz mu pewne opcje.

  • W tym przypadku określamy tryb strumieniowania, aby móc przetwarzać strumień klatek wideo.

  • Następnie wywołujesz metodę process, a wywołanie zwrotne z niej pobierze maskę, która jest zwracana i obliczana przez segmentację selfie.

  • Dane wejściowe to obraz z aparatu.

  • Wszystkie te interfejsy API używają typów na poziomie aplikacji, a nie nieprzetworzonych tensorów, więc programowanie odbywa się na bardzo wysokim poziomie i jest bardzo proste.

Modele niestandardowe w LiteRT

  • W drugiej części, czyli w przypadku modelu niestandardowego, użyjemy modelu PyTorch.

  • Myślę, że Chintan pobrał go z Kaggle lub Hugging Face…

  • Po prawej.

  • Tak, możesz też przekonwertować własne.

  • Możesz utworzyć własny model.

  • Przepraszam, wracam.

  • Tak wygląda ten stos.

  • Możesz przekonwertować i skwantyzować model PyTorch, aby uzyskać model LiteRT.

  • Następnie możesz rozpowszechniać go wraz z aplikacją w dowolny sposób.

  • Może być dołączony do aplikacji jako komponent lub pobrany osobno.

  • Obie metody są prawidłowe.

  • A to z kolei działa na środowisku wykonawczym LiteRT w usługach Google Play.

  • Dostępne są też jądra procesora do optymalizacji na procesorze, a ML Drift to nazwa akceleratora GPU.

  • Tak, jak powiedziałem, otrzymujesz model TFLite. Możesz go wytrenować samodzielnie lub znaleźć istniejący model. Obie opcje działają.

  • Konwersja z PyTorch wymaga tylko kilku wierszy kodu w Pythonie.

    import litert_torch
    
    model = my_models.Stylizer().eval()
    
    # Convert with torch.export under the hood
    edge_model = litert_torch.convert(
        model, sample_inputs)
    edge_model.export("stylizer_f32.tflite")
  • Wystarczy, że zainstalujesz LiteRT-Torch za pomocą pip, wywołasz litert_torch.convert, przekażesz sample_inputs, które mogą być losowymi danymi wejściowymi, i wyeksportujesz plik TFLite.

  • LiteRT-Torch to nowa nazwa ai-edge-torch, jeśli znasz to narzędzie.

  • Kwantyzacja jest bardzo prosta.

    # Python
    # previously ai_edge_quantizer
    from litert_quantizer import quantizer, recipe
    
    qt = quantizer.Quantizer("stylizer_f32.tflite")
    
    # int8 weights, float activations
    qt.load_quantization_recipe(
        recipe.dynamic_wi8_afp32())
    
    qt.quantize().export_model("stylizer_int8.tflite")
  • Importujesz kwantyzator i przepis z LiteRT Quantizer.

  • Podczas tworzenia kwantyzatora przekazujesz oryginalny model z reprezentacją zmiennoprzecinkową i przepis, który jest standardowym przepisem zalecanym dla GPU, który używa 8-bitowych wag liczb całkowitych, ale zachowuje aktywacje jako 32-bitowe liczby zmiennoprzecinkowe.

  • Następnie wystarczy wywołać funkcję quantize, a potem export_model, aby zapisać model wyjściowy.

  • Otrzymasz skwantyzowany model, który możesz uruchomić. Będzie on miał znacznie mniejsze wagi i będzie działał wydajniej.

Akceleracja GPU za pomocą interfejsu CompiledModel API

  • Tak, interfejs API CompiledModel i GPU to mocne strony tego urządzenia.

  • Jak wspomniał Chintan, oznacza to znaczne przyspieszenie w porównaniu ze starszymi GPU TFLite.

  • Dokładne liczby będą się nieco różnić w zależności od modelu, ale możesz oczekiwać 1,4 raza więcej.

  • Do 10 razy szybciej niż wnioskowanie na procesorze, więc to duża zaleta.

  • Jeśli większość z Was korzysta obecnie z modeli, prawdopodobnie uruchamiacie je na procesorze, przez co tracicie około 10-krotnie większą wydajność, którą można uzyskać dzięki GPU.

  • To naprawdę zachęca.

  • Co sprawia, że jest szybki?

  • Obsługujemy wiele rzeczy, na przykład asynchroniczne wykonywanie, dzięki czemu można pobrać AHardwareBuffer i przekazać go bezpośrednio lub bufor OpenGL z potoku renderowania aparatu i przekazać go bezpośrednio do bufora tensora.

  • Obsługujemy optymalizację bez kopiowania, więc gdy próbujesz przetwarzać dane z niskim budżetem opóźnienia, np. gdy musisz przetworzyć każdą klatkę w ciągu kilkudziesięciu milisekund, nawet zwykłe skopiowanie bufora pamięci może być nietrywialnym obciążeniem.

  • Dlatego w przypadku aplikacji, które wymagają bardzo wysokiej wydajności w czasie rzeczywistym, warto użyć optymalizacji bez kopiowania, którą obsługujemy.

  • Jak wspomniał Chintan, jest to rozwiązanie na wielu platformach z obsługą OpenGL, OpenCL i Metal jako backendów GPU.

  • I wreszcie, co nie mniej ważne, optymalizator ML Drift jest dostępny na zasadach open source.

  • Jest dostępny na licencji Apache.

  • Google niedawno udostępniło go jako open source.

  • OK, a tutaj jest kod aplikacji.

    // Kotlin
    // Build once, off the main thread.
    private val model: CompiledModel =
        CompiledModel.create(
            context.assets,
            "stylizer_int8.tflite",
            // Simple GPU setup!
            CompiledModel.Options(Accelerator.GPU),
            environment
        )
    
    // Reuse buffers across frames.
    private val inputBuffers  = model.createInputBuffers()
    private val outputBuffers = model.createOutputBuffers()
    
    fun stylize(input: FloatArray): FloatArray {
        inputBuffers[0].writeFloat(input)
        model.run(inputBuffers, outputBuffers) // sync
        return outputBuffers[0].readFloat()
    }
  • Jak widać, jest on dość mały i prosty.

  • Wystarczy, że utworzysz model raz, a potem możesz go używać w każdym kadrze.

  • W tym przypadku CompiledModel.create przekazuje plik .tflite.

  • Wystarczy określić, że chcesz uruchomić na GPU, a następnie skonstruować dane wejściowe i outputBuffers.

  • Następnie w głównej pętli, w której przetwarzasz każdą klatkę, wywołujesz model.run, przekazując dane wejściowe i wyjściowe.

  • Po napisaniu do inputBuffers zadzwoń do model.run, a następnie przeczytaj z outputBuffers.

  • OK.

  • Tak, a jeśli określisz tam GPU, będzie działać na GPU.

  • Jeśli określisz tam również procesor i GPU, spróbuje uruchomić GPU.

  • Jeśli z jakiegoś powodu GPU jest niedostępny, zostanie użyty CPU.

  • W niektórych przypadkach procesor może nie być wystarczająco wydajny dla aplikacji. Wtedy warto określić GPU w ten sposób.

  • Częściej jednak chcesz mieć procesor jako rozwiązanie zastępcze.

Korzystanie z LiteRT w usługach Google Play

  • OK.

  • Dlatego utworzyliśmy go z dołączonym LiteRT, który nie korzysta jeszcze z Usług Google Play.

  • Pokażę Ci, jak używać LiteRT w usługach Google Play.

  • Wprowadziliśmy 3 zmiany. Pierwsza dotyczy zależności.

    // Easier with CompiledModel API: 3 steps
    
    // 1. app/build.gradle: replace litert with play-services-litert
    - implementation 'com.google.ai.edge.litert:litert:...'
    + implementation 'com.google.android.gms:play-services-litert:17.0.0'  // also pulls in litert-api
  • Wystarczy, że zastąpisz zależność w pliku Gradle lub w innym miejscu, w którym określasz zależności pakietu Maven, niezależnie od używanego systemu kompilacji.

  • Usuń zależność litert lub dowolną zależność starszego pakietu Maven TensorFlow Lite i zastąp ją zależnością play-services-litert.

  • Spowoduje to również pobranie pakietu litert-api.

  • Jeśli piszesz warstwę pośrednią, która ma zależeć od LiteRT, ale nie ma znaczenia, czy środowisko wykonawcze pochodzi z aplikacji czy z Usług Google Play, możesz po prostu polegać na interfejsie LiteRT API i użyć środowiska jako parametru wejściowego.

  • Drugi krok to parametr środowiska.

  • W tym miejscu podajesz wstrzykiwanie zależności, aby określić, że chcesz używać LiteRT w Usługach Google Play.

  • Importujesz więc gms.litert.LiteRt i wywołujesz funkcję inicjowania, przekazując kontekst, czyli aktywność na Androidzie.

    // 2. Initialize the LiteRT Environment from Play services (context = your Activity)
    - val environment = Environment.create(...)
    + import com.google.android.gms.litert.LiteRt
    + val environment = LiteRt.initialize(context).await()
    
    // 3. Pass environment whenever you call CompiledModel.create
    
    // That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.
  • Jest to operacja asynchroniczna, więc musisz wywołać .await lub oprzeć resztę na wywołaniu zwrotnym.

  • Na koniec, gdy masz już to środowisko, przekazujesz je za każdym razem, gdy wywołujesz CompiledModel.create.

  • Dzięki temu będzie używać środowiska wykonawczego LiteRT z usług Google Play.

  • To wszystko.

  • Oznacza to, że pozostałe części aplikacji używają dokładnie tych samych interfejsów API LiteRT CompiledModel z interfejsu LiteRT API.

  • Pozostała część kodu wnioskowania nie zmienia się w przypadku korzystania z usług Google Play.

  • Migrację można przeprowadzać stopniowo.

  • Nie musisz robić tego od razu – możesz przenosić po jednym komponencie.

  • Jeśli masz dużą aplikację, warto przenieść każdy komponent, który używa LiteRT, a następnie możesz przenosić i testować po jednym komponencie.

  • Jedynym zastrzeżeniem jest to, że oszczędność miejsca uzyskasz dopiero po usunięciu ostatniej zależności od dołączonego środowiska wykonawczego.

  • Jeśli tak, pamiętaj, że nie należy mieszać obiektów między LiteRT w Usługach Google Play a dołączonym LiteRT.

  • Jeśli więc otrzymujesz tensory, skompilowane modele lub interpretery z LiteRT w usługach Google Play, nie przekazuj ich do dołączonego LiteRT ani odwrotnie.

  • Poza tym jednak łączenie tych elementów działa bez zarzutu.

  • OK.

  • To było tworzenie nowej aplikacji.

  • Teraz omówię, jak uaktualnić istniejącą aplikację.

  • Możesz mieć już aplikację, która korzysta z interfejsu Interpreter API.

  • To jest starszy interfejs API TFLite, który używa interpretera jako głównej klasy.

  • Po lewej stronie widzisz kod korzystający z interfejsu Interpreter API, a po prawej – nowy kod interfejsu CompiledModel API.

    // Dependencies (Gradle):
    // play-services-tflite-java and/or litert (bundled)
    
    // Init
    TfLite.initialize(context).await()
    
    // Load
    val interpreterOptions =
        InterpreterApi.Options().apply {
          runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
        }
    
    val interpreter =
        InterpreterApi.create(modelFile, interpreterOptions)
    
    // Prepare inputs/outputs
    val inputs = …
    val outputs = …
    
    // Execute
    interpreter.run(inputs, outputs)
    // Dependencies (Gradle):
    // play-services-litert
    
    // Init
    val environment =
      LiteRt.initialize(context).await()
    
    // Load
    val modelOptions = CompiledModel.Options(Accelerator.CPU)
    
    val model =
        CompiledModel.create(modelPath, modelOptions, environment)
    
    // Prepare inputs/outputs
    val inputBuffers = model.createInputBuffers()
    val outputBuffers = model.createOutputBuffers()
    
    // Execute
    model.run(inputBuffers, outputBuffers
  • Zmieniasz więc TfLite.initialize na LiteRt.initialize, co teraz zwraca środowisko.

  • Następnie przekazujesz środowisko do CompiledModel.create.

  • To niewielka zmiana, która nie zwiększa rozmiaru pakietu APK.

  • Na następnym slajdzie pokażemy, jak to zrobić za pomocą GPU, co jest kolejną opcją.

  • To jest dodatkowy kod, który jest potrzebny do włączenia GPU.

    // Dependencies (Gradle):
    // play-services-tflite-java and/or litert (bundled)
    
    // Init
    val initOptions = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true).build()
    TfLite.initialize(context, initOptions).await()
    val useGpu =
        TfLiteGpu.isGpuDelegateAvailable(context).await()
    
    // Load
    val interpreterOptions =
        InterpreterApi.Options().apply {
          runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
        }
    if (useGpu) {
        interpreterOptions.addDelegateFactory(
            GpuDelegateFactory());
    }
    val interpreter =
        InterpreterApi.create(modelFile, interpreterOptions)
    
    // Prepare inputs/outputs
    val inputs = …
    val outputs = …
    
    // Execute
    interpreter.run(inputs, outputs)
    // Dependencies (Gradle):
    // play-services-litert
    
    // Init
    val initOptions = LiteRtInitializationOptions.builder()
        .setEnableGpu(true).build()
    val environment = LiteRt.initialize(context, initOptions).await()
    
    // Load
    val modelOptions =
        CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
    
    val model =
        CompiledModel.create(modelPath, modelOptions, environment)
    
    // Prepare inputs/outputs
    val inputBuffers = model.createInputBuffers()
    val outputBuffers = model.createOutputBuffers()
    
    // Execute
    model.run(inputBuffers, outputBuffers)
  • Jak widać, kod w nowym interfejsie API do włączania GPU jest nieco prostszy niż wcześniej.

  • Pierwsze wywołanie setEnableGpu w opcjach inicjowania LiteRT, które przekazujesz do LiteRt.initialize, spowoduje wczytanie kodu akceleratora GPU do aplikacji.

  • Następnie, gdy tworzysz modelOptions i przekazujesz je do CompiledModel.create, określasz, który akcelerator będzie używany w przypadku konkretnego modelu, czy chcesz, aby inny model działał tylko na GPU, na GPU z rezerwowym CPU czy tylko na CPU.

  • OK.

  • Jak widać, włączenie GPU jest znacznie prostsze dzięki nowemu interfejsowi API.

  • Co dokładnie zyskujesz?

  • Chintan Ci o tym opowie.

  • OK.

  • Dziękuję, Fergus.

  • Porozmawiajmy o tym, co nam to wszystko daje.

  • Pamiętasz, że mieliśmy utworzyć aplikację? Zobaczmy, co udało nam się stworzyć.

  • To ja. Wykorzystaliśmy ML Kit, aby mnie znaleźć, więc segmentacja jest wykonywana przez gotowy interfejs API, taki jak ML Kit.

  • To jest moja głowa.

  • Następnie LiteRT używa innego modelu podobnego do przeniesienia stylu, aby pomalować tło.

  • Inne korzyści, o których wspominaliśmy, to oszczędność około 8 MB miejsca, jedno środowisko wykonawcze używane przez wszystkie aplikacje (lub przynajmniej te, które są tutaj udostępniane), automatyczne aktualizacje oraz szybszy procesor graficzny, który zapewnia blisko 30 klatek na sekundę w przypadku treści, które muszą być wyświetlane w czasie rzeczywistym, aby zapewnić użytkownikom bogate wrażenia.

  • Co więcej, nie musisz robić tego wszystkiego ręcznie.

  • Wprowadziliśmy też nową umiejętność w Androidzie, czyli opublikowaliśmy umiejętność Android LiteRT, która w kilka minut ulepsza systemy uczące się na urządzeniu.

  • Możesz więc zrobić kilka rzeczy: uaktualnić istniejącą aplikację, utworzyć nową aplikację, a także uaktualnić aplikację, aby korzystała z nowej integracji z Usługami Google Play.

  • Wszystkie te informacje są dostępne.

  • Link znajduje się na slajdzie, jest też na GitHubie i pojawi się w naszej dokumentacji oraz na naszym blogu.

  • To powinno być przydatne dla każdego, kto chce wkrótce wprowadzić zmiany.

  • Fergus powie nam, co będzie dalej.

Plan rozwoju i podsumowanie LiteRT

  • Dlatego stawiamy na AI na urządzeniu z LiteRT.

  • Nadal inwestujemy znaczne środki w ulepszanie akceleracji GPU i zakresu modeli oraz regularnie aktualizujemy LiteRT 2.x, zarówno w przypadku pakietu LiteRT open source, jak i pakietu LiteRT Maven w Usługach Google Play, który jest LiteRT w Usługach Google Play.

  • Będziemy też nadal zapewniać zgodność wsteczną.

  • Środowisko wykonawcze usług Google Play będzie nadal obsługiwać aplikacje utworzone za pomocą starszych pakietów SDK.

  • Tak.

  • To bardzo ważne dla naszych użytkowników i dla nas.

  • Pakiety SDK LiteRT 1.x są obecnie w trybie konserwacji, więc otrzymują tylko krytyczne poprawki zabezpieczeń.

  • Interfejs NNAPI, który wycofaliśmy w 2024 r., zostanie usunięty prawdopodobnie w 2027 r.

  • Jeśli więc używasz NNAPI, przełącz się na akcelerację GPU lub NPU z dołączonym LiteRT.

  • OK.

  • Tak.

  • Im szybciej przejdziesz na wersję 2.x i CompiledModel, tym mniej pracy będziesz mieć później.

  • Podsumowując, warto zapamiętać 3 rzeczy.

  • Dlatego twórz.

  • Zacznij od ML Kit. Jeśli spełnia Twoje potrzeby, to świetnie.

  • Jeśli jednak nie, użyj LiteRT w przypadku modeli niestandardowych.

  • Przejdź na LiteRT w usługach Google Play, aby zmniejszyć rozmiar pliku APK i korzystać ze wspólnego środowiska wykonawczego.

  • Rozważ też użycie interfejsu API CompiledModel, aby przyspieszyć i uprościć wnioskowanie na GPU.

  • Tak.

  • Wszystko jest opisane w naszej witrynie z dokumentacją LiteRT na AI Edge pod podanym adresem URL.

  • No więc tak.

  • Dziękujemy, że jesteście z nami. Nie możemy się doczekać, aby zobaczyć, co stworzycie.

Kod

Fragmenty kodu

Fragment kodu w języku Kotlin w 15:09 w filmie „Overview of the sample application”
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
    SelfieSegmenterOptions.Builder()
        .setDetectorMode(
            SelfieSegmenterOptions.STREAM_MODE)
        .build())

// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
  val image = InputImage.fromMediaImage(
      mediaImage, /* rotationDegrees= */ 0)
  segmenter.process(image)
      .addOnSuccessListener { mask -> … }
}
Fragment kodu w Pythonie w 17:34 w filmie „Custom models on LiteRT”
import litert_torch

model = my_models.Stylizer().eval()

# Convert with torch.export under the hood
edge_model = litert_torch.convert(
    model, sample_inputs)
edge_model.export("stylizer_f32.tflite")
Fragment kodu w Pythonie w 18:04 w filmie „Custom models on LiteRT”
# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe

qt = quantizer.Quantizer("stylizer_f32.tflite")

# int8 weights, float activations
qt.load_quantization_recipe(
    recipe.dynamic_wi8_afp32())

qt.quantize().export_model("stylizer_int8.tflite")
Fragment kodu w Kotlinie w 21:06 w filmie „GPU acceleration with CompiledModel API”
// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
    CompiledModel.create(
        context.assets,
        "stylizer_int8.tflite",
        // Simple GPU setup!
        CompiledModel.Options(Accelerator.GPU),
        environment
    )

// Reuse buffers across frames.
private val inputBuffers  = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()

fun stylize(input: FloatArray): FloatArray {
    inputBuffers[0].writeFloat(input)
    model.run(inputBuffers, outputBuffers) // sync
    return outputBuffers[0].readFloat()
}
Fragment kodu Groovy w 22:36 w filmie „Using LiteRT in usługach Google Play”
// Easier with CompiledModel API: 3 steps

// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0'  // also pulls in litert-api
Fragment kodu w języku Kotlin w 23:43 w filmie „Using LiteRT in usługach Google Play”
// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()

// 3. Pass environment whenever you call CompiledModel.create

// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.
Fragment kodu w języku Kotlin w 25:45 w filmie „Using LiteRT in usługi Google Play”
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)

// Init
TfLite.initialize(context).await()

// Load
val interpreterOptions =
    InterpreterApi.Options().apply {
      runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
    }

val interpreter =
    InterpreterApi.create(modelFile, interpreterOptions)

// Prepare inputs/outputs
val inputs = …
val outputs = …

// Execute
interpreter.run(inputs, outputs)
Fragment kodu w języku Kotlin w 25:45 w filmie „Using LiteRT in usługi Google Play”
// Dependencies (Gradle):
// play-services-litert

// Init
val environment =
  LiteRt.initialize(context).await()

// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)

val model =
    CompiledModel.create(modelPath, modelOptions, environment)

// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Execute
model.run(inputBuffers, outputBuffers
Fragment kodu w języku Kotlin w 26:25 w filmie „Using LiteRT in usługi Google Play”
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)

// Init
val initOptions = TfLiteInitializationOptions.builder()
    .setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
    TfLiteGpu.isGpuDelegateAvailable(context).await()

// Load
val interpreterOptions =
    InterpreterApi.Options().apply {
      runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
    }
if (useGpu) {
    interpreterOptions.addDelegateFactory(
        GpuDelegateFactory());
}
val interpreter =
    InterpreterApi.create(modelFile, interpreterOptions)

// Prepare inputs/outputs
val inputs = …
val outputs = …

// Execute
interpreter.run(inputs, outputs)
Fragment kodu w Kotlinie w 26:25 w filmie „Using LiteRT in usługi Google Play”
// Dependencies (Gradle):
// play-services-litert

// Init
val initOptions = LiteRtInitializationOptions.builder()
    .setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()

// Load
val modelOptions =
    CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)

val model =
    CompiledModel.create(modelPath, modelOptions, environment)

// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Execute
model.run(inputBuffers, outputBuffers)