Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Einleitung

Hallo!

In diesem Artikel werde ich meine Erfahrungen beim Aufbau einer Mikroservice-Architektur für ein Projekt, das neuronale Netze verwendet, teilen.

Lassen Sie uns über die Anforderungen an die Architektur sprechen, verschiedene Strukturdiagramme ansehen, jeden der Komponenten der fertigen Architektur analysieren und die technischen Metriken der Lösung bewerten.

Viel Spaß beim Lesen!

Ein paar Worte zur Aufgabe und ihrer Lösung

Die grundlegende Idee ist, basierend auf Fotos die Attraktivität einer Person auf einer Skala von eins bis zehn zu bewerten.

In diesem Artikel werden wir von der Beschreibung sowohl der verwendeten neuronalen Netze als auch des Prozesses der Datenvorbereitung und des Trainings absehen. In einem der nächsten Beiträge werden wir jedoch auf die Analyse des Bewertungs-Pipelines auf einer tieferen Ebene zurückkommen.

Jetzt werden wir den Bewertungs-Pipeline auf einer hohen Ebene durchgehen, wobei wir den Fokus auf die Interaktion der Mikroservices im Kontext der Gesamtarchitektur des Projekts legen. 

Bei der Arbeit an der Bewertungs-Pipeline wurde die Aufgabe in folgende Komponenten dekonstruiert:

  1. Gesichtserkennung auf Fotos
  2. Bewertung jedes Gesichts
  3. Rendering des Ergebnisses

Das erste wird mithilfe von einem vortrainierten MTCNNgelöst. Für das zweite wurde ein konvolutionales neuronales Netz auf PyTorch trainiert, wobei als Backbone verwendet wurde ResNet34 – aus dem Balance zwischen "Qualität / Geschwindigkeit der Inferenz auf CPU".

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Funktionsdiagramm der Bewertungs-Pipeline

Analyse der Anforderungen an die Architektur des Projekts

Im Lebenszyklus ML sind die Arbeitsschritte an der Architektur und der Automatisierung des Modellausrollens oft die zeit- und ressourcenintensivsten.

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Lebenszyklus eines ML-Projekts

Dieses Projekt ist da keine Ausnahme – es wurde beschlossen, die Bewertungs-Pipeline in einen Online-Service zu verpacken, was ein Eintauchen in die Architektur erforderte. Es wurden folgende grundlegende Anforderungen festgelegt:

  1. Zentralisierte Log-Speicherung – alle Dienste sollten Protokolle an einem Ort schreiben, die einfach zu analysieren sind.
  2. Möglichkeit der horizontalen Skalierung des Bewertungsdienstes – als wahrscheinlichster Bottleneck
  3. Es sollten gleich viele CPU-Ressourcen für die Bewertung jedes Bildes bereitgestellt werden – um Ausreißer in der Verteilung der Zeit für die Inferenz zu vermeiden.
  4. Schnelle (Neu-)Bereitstellung sowohl der spezifischen Dienste als auch des gesamten Stacks.
  5. Die Möglichkeit, bei Bedarf gemeinsame Objekte in verschiedenen Diensten zu nutzen.

Architektur

Nach der Analyse der Anforderungen wurde deutlich, dass die Mikroservice-Architektur praktisch perfekt passt.

Um unnötigen Kopfschmerzen zu entgehen, wurde Telegram API als Frontend gewählt.

Zunächst betrachten wir das Strukturdiagramm der fertigen Architektur, anschließend werden wir jedes der Komponenten beschreiben und den Prozess der erfolgreichen Bildverarbeitung formalisieren.

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Strukturdiagramm der fertigen Architektur

Lassen Sie uns näher auf jede der Komponenten des Diagramms eingehen und deren Single Responsibility im Prozess der Bildbewertung kennzeichnen.

Mikroservice „attrai-telegram-bot“

Dieser Mikroservice kapselt alle Interaktionen mit der Telegram API. Es lassen sich zwei Hauptszenarien unterscheiden – die Arbeit mit dem Benutzerbild und die Arbeit mit dem Ergebnis der Bewertungs-Pipeline. Wir werden beide Szenarien im Allgemeinen durchgehen.

Beim Erhalt einer Benutzer-Nachricht mit einem Bild:

  1. Es erfolgt eine Filterung, die aus den folgenden Prüfungen besteht:
    • Vorhandensein der optimalen Bildgröße
    • Anzahl der Bilder des Benutzers, die sich bereits in der Warteschlange befinden
  2. Nach Bestehen der ersten Filterung wird das Bild im Docker-Volume gespeichert.
  3. In die Warteschlange "to_estimate" wird eine Aufgabe produziert, die unter anderem den Pfad zum Bild, das sich in unserem Volume befindet, enthält.
  4. Wenn die oben genannten Schritte erfolgreich abgeschlossen sind, erhält der Benutzer eine Nachricht mit der ungefähren Verarbeitungszeit des Bildes, die basierend auf der Anzahl der Aufgaben in der Warteschlange berechnet wird. Bei einem Fehler wird der Benutzer ausdrücklich darüber informiert – durch das Senden einer Nachricht mit Informationen darüber, was schiefgelaufen sein könnte.

Dieser Mikroservice fungiert auch als Celery-Worker und lauscht der Warteschlange "after_estimate", die für Aufgaben bestimmt ist, die durch die Bewertungs-Pipeline gegangen sind.

Beim Erhalt einer neuen Aufgabe aus "after_estimate":

  1. Wenn das Bild erfolgreich verarbeitet wurde, senden wir das Ergebnis an den Benutzer, andernfalls informieren wir über den Fehler.
  2. Wir löschen das Bild, das das Ergebnis der Bewertungs-Pipeline darstellt.

Mikroservice zur Bewertung „attrai-estimator“

Dieser Mikroservice ist ein Celery-Worker und kapselt alles, was mit der Bildbewertungs-Pipeline zu tun hat. Der Arbeitsalgorithmus ist einfach – wir werden ihn durchgehen.

Bei Erhalt einer neuen Aufgabe aus "to_estimate":

  1. Wir leiten das Bild durch die Bewertungs-Pipeline:
    1. Wir laden das Bild in den Speicher.
    2. Wir bringen das Bild auf die gewünschte Größe
    3. Wir finden alle Gesichter (MTCNN)
    4. Wir bewerten alle Gesichter (wir packen die zuvor gefundenen Gesichter in einen Batch und inferenzen ResNet34)
    5. Wir rendern das endgültige Bild
      1. Wir zeichnen Bounding Boxes
      2. Wir zeichnen die Bewertungen
  2. Wir entfernen das Benutzerbild (Originalbild)
  3. Wir speichern den Output aus der Bewertungs-Pipeline
  4. Wir legen die Aufgabe in die Warteschlange „after_estimate“, die vom oben erläuterten Microservice „attrai-telegram-bot“ gehört wird

Graylog (+ MongoDB + Elasticsearch)

Graylog ist eine Lösung für das zentrale Log-Management. In diesem Projekt wurde es für seinen ursprünglichen Zweck verwendet.

Die Wahl fiel auf ihn und nicht auf den allen bekannten ELK Stack, wegen der Bequemlichkeit der Arbeit mit ihm aus Python. Alles, was für das Logging in Graylog erforderlich ist, ist es, GELFTCPHandler aus dem Paket graypy zu den anderen Root Logger Handlers unseres Python-Microservices hinzuzufügen.

Ich, als jemand, der vorher nur mit dem ELK-Stack gearbeitet hat, hatte insgesamt positive Erfahrungen bei der Arbeit mit Graylog. Das einzige, was enttäuscht, ist die Überlegenheit der Funktionen von Kibana gegenüber der Web-Oberfläche von Graylog.

RabbitMQ

RabbitMQ ist ein Nachrichtenbroker basierend auf dem AMQP-Protokoll.

In diesem Projekt wurde er als der stabilste und bewährte Broker für Celery verwendet und arbeitete im dauerhaften Modus.

Redis

Redis ist eine NoSQL-Datenbank, die mit Datensensoren vom Typ „Schlüssel – Wert“ arbeitet

Manchmal besteht die Notwendigkeit, in verschiedenen Python-Microservices gemeinsame Objekte zu verwenden, die bestimmte Datenstrukturen implementieren.

Zum Beispiel wird in Redis eine Hashmap vom Typ „telegram_user_id => Anzahl aktiver Aufgaben in der Warteschlange“ gespeichert, die es ermöglicht, die Anzahl der Anfragen von einem Benutzer auf einen bestimmten Wert zu begrenzen und so DoS-Angriffe zu verhindern.

Wir formalisieren den Prozess der erfolgreichen Bildverarbeitung

  1. Der Benutzer sendet ein Bild an den Telegram-Bot
  2. „attrai-telegram-bot“ erhält die Nachricht von der Telegram-API und analysiert sie
  3. Die Aufgabe mit dem Bild wird in die asynchrone Warteschlange „to_estimate“ hinzugefügt
  4. Der Benutzer erhält eine Nachricht mit der voraussichtlichen Bewertungszeit
  5. „attrai-estimator“ nimmt die Aufgabe aus der Warteschlange „to_estimate“, führt sie durch die Bewertungs-Pipeline und produziert die Aufgabe in der Warteschlange „after_estimate“
  6. „attrai-telegram-bot“, der die Warteschlange „after_estimate“ hört, sendet das Ergebnis an den Benutzer

DevOps

Schließlich, nach der Überprüfung der Architektur, können wir zum nicht weniger interessanten Teil übergehen – DevOps

Docker Swarm

 

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Docker Swarm  — ein Cluster-System, dessen Funktionalität innerhalb der Docker Engine realisiert ist und sofort verfügbar ist.

Durch die Verwendung von „Roya“ können alle Knoten unseres Clusters in zwei Typen unterteilt werden – Worker und Manager. Auf Maschinen des ersten Typs werden Gruppen von Containern (Stäcke) bereitgestellt, während Maschinen des zweiten Typs für Skalierung, Lastverteilung und andere coole Funktionen. Manager fungieren standardmäßig auch als Worker.

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Cluster mit einem Leader-Manager und drei Workern

Die minimal mögliche Größe eines Clusters beträgt 1 Knoten, wodurch eine einzige Maschine gleichzeitig als Leader-Manager und Worker agiert. Basierend auf der Projektgröße und den minimalen Anforderungen an Ausfallsicherheit wurde diese Vorgehensweise gewählt.

Vorausblickend kann ich sagen, dass seit der ersten Produktionseinführung Mitte Juni keine Probleme im Zusammenhang mit dieser Clusterorganisation aufgetreten sind (aber das bedeutet nicht, dass eine solche Organisation in mittelgroßen Projekten, die Anforderungen an die Ausfallsicherheit haben, in irgendeiner Weise akzeptabel ist).

Docker Stack

Im „Roya“-Modus ist der Einsatz von Stacks (Sammlungen von Docker-Services) verantwortlich docker stack

Es unterstützt Docker-Compose-Konfigurationen und ermöglicht darüber hinaus die Nutzung von Deploy-Parametern.  

Beispielsweise wurden mit diesen Parametern die Ressourcen für jede der Instanzen des Bewertung-Mikroservices beschränkt (wir weisen N Instanzen N Kerne zu, und im Mikroservice beschränken wir die Anzahl der Kerne, die von PyTorch verwendet werden, auf einen).

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

Es ist wichtig zu beachten, dass Redis, RabbitMQ und Graylog – Stateful-Services sind und es nicht so einfach ist, sie wie „attrai-estimator“ zu skalieren.

Vorweg genommen — warum nicht Kubernetes?

Es scheint, dass die Nutzung von Kubernetes in kleinen und mittelgroßen Projekten überflüssig ist; die gesamte notwendige Funktionalität kann von Docker Swarm erhalten werden, das recht benutzerfreundlich für Container-Orchestrierung ist und eine niedrige Einstiegshürde hat.

Infrastruktur

Das Ganze wurde auf einem VDS mit folgenden Eigenschaften bereitgestellt:

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

Nach lokalen Lasttests schien es, dass bei einem starken Anstieg an Nutzern diese Maschine gerade genug Leistung bietet.

Aber direkt nach dem Deployment habe ich einen Link zu einem der beliebtesten Imageboards in der GUS gepostet (ja, genau diesem), woraufhin die Leute interessiert waren und der Dienst in wenigen Stunden erfolgreich zehntausende Bilder verarbeitet hat. Dabei wurden zu Spitzenzeiten die CPU- und RAM-Ressourcen nicht einmal zur Hälfte genutzt.

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze
Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Ein wenig Grafik

Anzahl der einzigartigen Benutzer und Bewertungsanfragen seit dem Deployment, je nach Tag

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Verteilung der Inferrenzzeit des Bewertungs-Pipelines

Allgemeiner Überblick über die Architektur des Dienstes zur Bewertung des Aussehens auf der Grundlage neuronaler Netze

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.

Zusammenfassend kann ich sagen, dass die Architektur und der Ansatz zur Orchestrierung von Containern sich voll und ganz bewährt haben – selbst zu Spitzenzeiten gab es keine Ausfälle oder Verzögerungen bei der Bearbeitungszeit. 

Ich denke, kleine und mittelgroße Projekte, die in ihrem Prozess die Echtzeiteinferrenz von neuronalen Netzen auf CPU nutzen, können die in diesem Artikel beschriebenen Praktiken erfolgreich übernehmen.

Ich füge hinzu, dass der ursprüngliche Artikel länger war, aber um einen Longread zu vermeiden, habe ich einige Punkte in diesem Artikel weggelassen – wir werden in zukünftigen Veröffentlichungen darauf zurückkommen.

Den Bot kannst du auf Telegram antippen – @AttraiBot, er wird mindestens bis Ende Herbst 2020 funktionieren. Ich erinnere daran – es werden keine Benutzerdaten gespeichert – weder die ursprünglichen Bilder noch die Ergebnisse des Bewertungs-Pipelines – alles wird nach der Verarbeitung gelöscht.

Quelle: habr.com

60GB SSD 8Gb DDR4