Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Wprowadzenie

Cześć!

W tym artykule podzielę się doświadczeniem w budowie architektury mikroserwisów dla projektu opartego na sieciach neuronowych.

Porozmawiamy o wymaganiach dotyczących architektury, przyjrzymy się różnym diagramom strukturalnym, omówimy każdy z komponentów gotowej architektury, a także ocenimy metryki techniczne rozwiązania.

Życzymy miłej lektury!

Kilka słów o zadaniu i jego rozwiązaniu

Główna idea polega na tym, aby na podstawie zdjęcia ocenić atrakcyjność osoby w skali dziesięciopunktowej.

W tym artykule odejdziemy od opisu zarówno używanych sieci neuronowych, jak i procesu przygotowania danych i uczenia. Niemniej jednak w jednym z kolejnych publikacji na pewno wrócimy do analizy pipeline'u oceny na głębszym poziomie.

Teraz przejdziemy przez pipeline oceny na poziomie ogólnym, koncentrując się na interakcji mikroserwisów w kontekście ogólnej architektury projektu. 

Przy pracy nad pipeline'em oceny atrakcyjności zadanie zostało zdekomponowane na następujące składniki:

  1. Wydobywanie twarzy ze zdjęć
  2. Ocena każdej z twarzy
  3. Renderowanie wyniku

Pierwsze zadanie realizowane jest przez wytrenowany MTCNN. Dla drugiego zadania została wytrenowana sieć konwolucyjna w PyTorch, użyto jako backbone'a ResNet34 – z równowagi pomiędzy „jakością / szybkością inferencji na CPU”

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Funkcjonalny diagram pipeline'u oceny

Analiza wymagań dotyczących architektury projektu

W cyklu życia - wsparcie. projektu etapy pracy nad architekturą i automatyzacją wdrażania modelu są często jednymi z najbardziej czasochłonnych i kosztownych zasobowo.

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Cykl życia projektu ML

Ten projekt nie jest wyjątkiem – podjęto decyzję o opakowaniu pipeline'u oceny w serwis online, w związku z czym należało zgłębić architekturę. Wyznaczono następujące podstawowe wymagania:

  1. Jednolity magazyn logów – wszystkie usługi powinny zapisywać logi w jednym miejscu, powinny być łatwe do analizy
  2. Możliwość horyzontalnego skalowania usługi oceny - jako najbardziej prawdopodobny wąskie gardło
  3. Na ocenę każdego zdjęcia powinno być przeznaczone tej samej ilości zasobów procesora - aby uniknąć odchyleń w rozkładzie czasu na inferencję
  4. Szybkie (prze)wdrożenie zarówno konkretnych usług, jak i całego stosu
  5. Możliwość, w razie potrzeby, użycia wspólnych obiektów w różnych usługach

Architektura

Po analizie wymagań stało się oczywiste, że architektura mikroserwisowa idealnie się wpasowuje.

Aby pozbyć się niepotrzebnego bólu głowy, jako frontend wybrano Telegram API.

Na początku rozważmy diagram strukturalny gotowej architektury, następnie przejdziemy do opisu każdego z komponentów oraz sformalizujemy proces skutecznego przetwarzania obrazu.

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Diagram strukturalny gotowej architektury

Porozmawiajmy bardziej szczegółowo o każdym z komponentów diagramu, oznaczymy ich Single Responsibility w procesie oceny obrazu.

Mikroserwis „attrai-telegram-bot”

Ten mikroserwis inkapsuluje wszystkie interakcje z API Telegrama. Można wyróżnić dwa główne scenariusze – praca z obrazem użytkownika i praca z wynikiem potoku oceny. Rozważymy oba scenariusze w ogólnym zarysie.

Przy otrzymaniu wiadomości użytkownika z obrazem:

  1. Przeprowadzana jest filtracja, składająca się z następujących sprawdzeń:
    • Obecności optymalnego rozmiaru obrazu
    • Liczby obrazów użytkownika, które już znajdują się w kolejce
  2. Po przejściu wstępnej filtracji obraz jest zapisywany w wolumenie Docker
  3. Do kolejki „to_estimate” dodawana jest taska, w której znajduje się między innymi ścieżka do obrazu znajdującego się w naszym wolumenie
  4. Jeśli powyższe etapy zostaną pomyślnie ukończone – użytkownik otrzyma wiadomość z przybliżonym czasem przetwarzania obrazu, który obliczany jest na podstawie liczby zadań w kolejce. W przypadku błędu użytkownik zostanie wyraźnie o tym poinformowany – poprzez wysłanie wiadomości z informacją o tym, co mogło pójść nie tak.

Ten mikroserwis, jako worker Celery, nasłuchuje kolejkę „after_estimate”, która jest przeznaczona do zadań, które przeszły przez potok oceny.

Przy otrzymaniu nowego zadania z „after_estimate”:

  1. Jeśli obraz został przetworzony pomyślnie – wysyłamy wynik do użytkownika, jeśli nie – informujemy o błędzie
  2. Usuwamy obraz, który jest wynikiem potoku oceny

Mikroserwis oceny „attrai-estimator”

Ten mikroserwis jest workerem Celery i inkapsuluje wszystko, co związane jest z potokiem oceny obrazu. Algorytm działania jest jeden – przeanalizujemy go.

Przy otrzymaniu nowego zadania z „to_estimate”:

  1. Przepuszczamy obraz przez potok oceny:
    1. Ładujemy obraz do pamięci
    2. Dostosowujemy obraz do wymaganych rozmiarów
    3. Wykrywamy wszystkie twarze (MTCNN)
    4. Oceniamy wszystkie twarze (opakowujemy wcześniej znalezione twarze w batch i wykonujemy inferencję ResNet34)
    5. Renderujemy ostateczny obraz
      1. Rysujemy bounding boxy
      2. Rysujemy oceny
  2. Usuwamy oryginalny obraz użytkownika
  3. Zapisujemy wynik z pipeline'u oceny
  4. Dodajemy zadanie do kolejki 'after_estimate', którą monitoruje wcześniej opisany mikrousług 'attrai-telegram-bot'

Graylog (+ mongoDB + Elasticsearch)

Graylog — to rozwiązanie do centralnego zarządzania logami. W tym projekcie było używane zgodnie z jego przeznaczeniem.

Postawiliśmy na niego, a nie na znany wszystkim ELK styk, z powodu wygody pracy z nim w Pythonie. Wszystko, co musimy zrobić, aby logować w Graylog, to dodać GELFTCPHandler z pakietu graypy do pozostałych handlerów root loggera naszego mikrousługi w Pythonie.

Jako osoba, która wcześniej pracowała tylko ze stakiem ELK, w ogóle miałem pozytywne doświadczenia podczas pracy z Graylog. Jedyną rzeczą, która zawodzi, jest przewaga funkcji Kibany nad interfejsem webowym Graylog.

RabbitMQ

RabbitMQ — to broker wiadomości oparty na protokole AMQP.

W tym projekcie był używany jako najbardziej stabilny i sprawdzony w czasie broker dla Celery i działał w trybie durable.

Redis

Redis — to baza danych NoSQL, która operuje na strukturach danych typu 'klucz — wartość'

Czasami zachodzi potrzeba użycia wspólnych obiektów w różnych mikrousługach Pythona, realizujących jakieś struktury danych.

Na przykład, w Redis przechowywany jest hashmap w postaci 'telegram_user_id => liczba aktywnych zadań w kolejce', co pozwala ograniczyć liczbę zapytań od jednego użytkownika do określonej wartości i tym samym zapobiega atakom DoS.

Formalizujemy proces pomyślnego przetwarzania obrazu

  1. Użytkownik wysyła obraz do bota Telegram
  2. 'attrai-telegram-bot' otrzymuje wiadomość z Telegram API i ją analizuje
  3. Zadanie z obrazem dodawane jest do asynchronicznej kolejki 'to_estimate'
  4. Użytkownik otrzymuje wiadomość z przewidywanym czasem oceny
  5. 'attrai-estimator' pobiera zadanie z kolejki 'to_estimate', przetwarza je przez pipeline oceny i przekazuje zadanie do kolejki 'after_estimate'
  6. 'attrai-telegram-bot', monitorujący kolejkę 'after_estimate', wysyła wynik do użytkownika

DevOps

Wreszcie, po przeglądzie architektury, możemy przejść do nie mniej interesującej części — DevOps

Czy to oznacza, że można używać tego samego pliku docker-compose w

 

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Czy to oznacza, że można używać tego samego pliku docker-compose w  — system klasteryzacji, której funkcje są realizowane wewnątrz Docker Engine i dostępne od razu.

Dzięki «roju», wszystkie węzły naszego klastra można podzielić na 2 typy – worker i manager. Na maszynach pierwszego typu uruchamiane są grupy kontenerów (staki), maszyny drugiego typu odpowiadają za skalowanie, balansowanie i inne świetne funkcje. Menedżerowie domyślnie są także workerami.

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Klaster z jednym liderem managerem i trzema workerami

Minimalny możliwy rozmiar klastra to 1 węzeł, jedyna maszyna będzie jednocześnie pełnić rolę lidera managera i workera. W oparciu o rozmiar projektu oraz minimalne wymagania dotyczące odporności na awarie podjęto decyzję o wykorzystaniu tego podejścia.

Wyprzedzam fakty mówiąc, że od czasu pierwszej produkcyjnej dostawy w połowie czerwca nie było problemów związanych z organizacją tego klastra (ale to nie oznacza, że taka organizacja jest w ogóle dopuszczalna w dowolnych projektach średniej i dużej wielkości, które mają wymagania dotyczące odporności na awarie).

Docker Stack

W trybie «roju» za wdrożenie stacków (zestawów usług docker) odpowiada docker stack

Obsługuje konfiguracje docker-compose, pozwalając dodatkowo na użycie parametrów wdrożenia.  

Na przykład, dzięki tym parametrom ograniczono zasoby na każdy z instancji mikroserwisu oceny (przydzielamy na N instancji N rdzeni, w samym mikroserwisie ograniczamy liczbę rdzeni używanych przez PyTorch do jednego)

attrai_estimator:
  image: 'erqups/attrai_estimator:1.2'
  deploy:
    replicas: 4
    resources:
      limits:
        cpus: '4'
    restart_policy:
      condition: on-failure
      …

Ważne jest, aby zauważyć, że Redis, RabbitMQ i Graylog to usługi stateful i nie będzie tak łatwo skalować ich jak «attrai-estimator»

Wyprzedzając pytanie – dlaczego nie Kubernetes?

Wydaje się, że użycie Kubernetes w projektach małych i średnich to nadmiar, cały potrzebny funkcjonalność można uzyskać z Docker Swarm, który jest stosunkowo przyjazny dla użytkownika jako orkiestrator kontenerów i ma niski próg wejścia.

Infrastruktura

Wszystko to zostało wdrożone na VDS o następujących charakterystykach:

  • CPU: 4 rdzenia Intel® Xeon® Gold 5120 CPU @ 2.20GHz
  • RAM: 8 GB
  • SSD: 160 GB

Po lokalnym teście obciążeniowym wydawało się, że przy poważnym napływie użytkowników ta maszyna będzie wystarczająca.

Jednak zaraz po wdrożeniu opublikowałem link do jednej z najpopularniejszych w krajach WNP stron z obrazkami (tak, tej właśnie), po czym ludzie się zainteresowali i w ciągu kilku godzin serwis pomyślnie przetworzył dziesiątki tysięcy obrazów. W momencie szczytowym zasoby CPU i RAM nie były wykorzystywane nawet w połowie.

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych
Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Jeszcze trochę grafiki

Liczba unikalnych użytkowników i zapytań o oceny od momentu wdrożenia, w zależności od dnia

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Rozkład czasu inferencji pipeline'u oceny

Ogólny przegląd architektury usługi w celu oceny wyglądu opartego na sieciach neuronowych

Wnioski

Podsumowując, mogę powiedzieć, że architektura i podejście do orkiestracji kontenerów całkowicie się sprawdziły — nawet w momentach szczytowych nie było awarii ani spowolnień w czasie przetwarzania. 

Myślę, że projekty małych i średnich rozmiarów, które wykorzystują w swoim procesie inferencję w czasie rzeczywistym sieci neuronowych na CPU, mogą skutecznie przyjąć praktyki opisane w tym artykule.

Dodam, że pierwotnie artykuł był większy, ale aby nie publikować długiego tekstu, postanowiłem pominąć niektóre kwestie — wrócimy do nich w następnych publikacjach.

Można poklikać bota na Telegramie — @AttraiBot, będzie działał przynajmniej do końca jesieni 2020 roku. Przypominam — żadne dane użytkowników nie są przechowywane — ani oryginalne obrazy, ani wyniki pipeline'u oceny — wszystko jest usuwane po przetworzeniu.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster