Modell-Deployment: Wie Sie ein Machine-Learning-Modell an Kunden liefern


Anton Shemyakov


Herzlichen Glückwunsch! Sie haben Ihr Machine Learning-Modell erfolgreich trainiert. Die Gewichte sind im Projektverzeichnis auf Ihrer Festplatte gespeichert. Die Skripte zum Laden des Modells und zur Durchführung von Inferenz funktionieren wie erwartet, und das Modell erreicht die gewünschte Leistung auf dem Testdatensatz. Jetzt stehen Sie vor der Herausforderung, die Modellvorhersagen für jeden zugänglich zu machen, der daran interessiert ist, Vorhersagen damit zu generieren.

Die Bereitstellung oder der Einsatz eines Modells ist ein entscheidender Schritt bei der Erstellung einer wirkungsvollen Machine-Learning-Anwendung, und dieser Blogbeitrag wird Sie Schritt für Schritt durch eine mögliche Lösung dieser Herausforderung führen. Systeme für Modelldeployments gibt es in allen Formen und Größen, von einfach bis hochkomplex. In diesem Blogbeitrag konzentrieren wir uns jedoch auf einen praktischen und einfachen Ansatz. Die vorgeschlagene Lösung könnte ein solider Ausgangspunkt sein, um Modellvorhersagen für Kunden bereitzustellen und erlaubt Erweiterungen, falls zusätzliche Anforderungen entstehen.

Stellen wir uns vor, dass wir ein Modell zur Textklassifikation entwickelt haben, das Menschen vor Betrügern im Internet schützen soll. Es nimmt eine verdächtige E-Mail als Eingabe und führt eine binäre Klassifikation durch, um mit hoher Genauigkeit zu bestimmen, ob der Absender bösartige Absichten hat. Mit diesem mentalen Bild im Hinterkopf, lassen Sie uns in das Tutorial eintauchen.


Erstellen einer REST-API


Wie würde ein Datenwissenschaftler Modellvorhersagen für ein Textstück generieren? Wahrscheinlich würde er das Modell in ein Jupyter-Notebook laden und die Methode „predict“ ausführen. Leider ist Ihr durchschnittlicher Kunde nicht mit Python und Jupyter-Notebook vertraut – alltägliche Werkzeuge für Datenwissenschaftler. Es gibt jedoch ein Werkzeug, mit dem fast jeder vertraut ist: den Webbrowser. Webbrowser wie Google Chrome, Edge, Safari oder Firefox haben das Potenzial, Ihr Modell verfügbar zu machen, wenn sie richtig damit kommunizieren können.

Ein Großteil der Kommunikation im Internet erfolgt über das HTTP-Protokoll, das für ein Client-Server-Modell konzipiert ist. In diesem Modell gibt es eine Entität, die als Server bezeichnet wird und kontinuierlich eingehende Nachrichten überwacht, und eine Entität, die als Client bezeichnet wird und Anfragen sendet. Wenn der Server eine Anfrage vom Client erhält, verarbeitet er die Anfrage auf vordefinierte Weise und sendet eine Antwort zurück. Das HTTP-Protokoll definiert das Format der zirkulierenden Nachrichten, einschließlich Methoden, Header, Antwortcodes, Nachrichtennutzlast und so weiter. Mehr über HTTP können Sie hier erfahren. Ein gültiges Anfrage-Antwort-Paar von Nachrichten könnte so aussehen:

Anfrage:

POST /predict HTTP/1.1
Host: example.com
Content-Type: text/plain
Content-Length: 44
Some text that I want to send to your model.

Antwort:

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 5
false

Wie Sie sehen können, gibt es bestimmte Regeln für den Aufbau von HTTP-Nachrichten, aber im Kern sind es Textstücke.

Um Modellvorhersagen über HTTP verfügbar zu machen, müssen Sie einen Server erstellen, indem Sie den Modellcode in etwas einbinden, das als REST-API bezeichnet wird. REST steht für representational state transfer und API bedeutet application programming interface, aber diese Namen sind nicht wichtig. Wichtig ist, dass eine REST-API eine universelle Schnittstelle für Ihr Modell erstellt, die Eingaben aus Text (oder präziser gesagt einer HTTP-Anfrage) erhält und das Ergebnis als Text an den Absender zurücksendet. Als Entwickler ist es Ihre Verantwortung zu definieren, welche Nachrichten Ihre REST-API akzeptiert und wie sie darauf reagiert.

Ein Beispiel für eine Bibliothek zur Erstellung von REST-APIs in Python ist FastAPI, ein weiteres ist Flask. Diese Werkzeuge erleichtern die Erstellung einfacher REST-APIs, aber ihre Beherrschung erfordert erhebliche Anstrengungen.

Hier ist ein Beispiel für die Implementierung einer grundlegenden Modellvorhersage-API mit FastAPI:

from fastapi import Body, FastAPI

from my_model import MyModel # import model class

app = FastAPI() # create FastAPI application
model = MyModel() # create an instance of the model that will make predictions


@app.post("/predict") # declare a path operation function that is called on a POST request at /predict endpoint
async def predict(text: str = Body()) -> bool: # the function expects text in request body and returns either "true" or "false"
    return model(text) == 1 # run model inference and transform binary output to boolean

Sie können hier mehr über den Aufbau von REST-APIs in Python erfahren.


Containerisierung eines Dienstes


Angenommen, Sie haben erfolgreich eine REST-API-Anwendung implementiert, die Vorhersagen von Ihrem Modell über HTTP zurückgibt. Eine solche Anwendung bezeichnen wir als Service. Da der Deployment-Service die Rolle eines Servers im Client-Server-Modell spielt, muss er kontinuierlich laufen - die ganze Zeit! Schließlich könnten Anfragen von potenziellen Kunden jederzeit kommen. Natürlich ist Ihr persönlicher Computer aus vielen Gründen eine schlechte Wahl, um den Dienst zu betreiben; zum Beispiel würde er ständig einen Teil der Ressourcen Ihres PCs verbrauchen. Die beste Hardwarewahl, um die Anwendung zu betreiben, ist ein dedizierter Computerknoten, ein Server. Lassen Sie uns für den Moment die Frage ignorieren, wo ein Server bereitgestellt werden kann und uns auf eine neue aufkommende Herausforderung konzentrieren, die jedem vertraut ist, der versucht hat, seinen Code auf einem anderen Computer auszuführen.

Noch bevor Sie ein Machine-Learning-Modell trainieren, müssen Sie die Arbeitsumgebung korrekt einrichten, zum Beispiel das Betriebssystem und die Python-Pakete installieren oder Umgebungsvariablen definieren. Diese Umgebung sollte genau auf einem anderen Computer repliziert werden, um sicherzustellen, dass die Anwendung fehlerfrei läuft und das ist eine herausfordernde Ingenieursaufgabe. Wenn es nur eine Möglichkeit gäbe, eine Art Container zu erstellen, in dem die Anwendung zusammen mit allen Abhängigkeiten und Anweisungen geladen wird, wie sie ausgeführt werden soll! Dann könnte spezielle Software diesen Container auf jedem Server ausführen, unabhängig von der Systemumgebung. Zum Glück gibt es eine Möglichkeit, eine Anwendung zusammen mit ihren Abhängigkeiten in einen Container zu packen; die Technologie heißt Containerisierung und das Werkzeug zur Erstellung und Ausführung von Containern heißt Docker.

Ein Container ist ähnlich wie eine tatsächliche laufende Instanz eines Programms, und in der Docker-Welt wird die ausführbare Datei zur Erstellung eines Containers als Image bezeichnet. Um Ihren Service zu containerisieren, benötigen Sie eine Dockerfile, die genau beschreibt, wie ein Image aus Ihrem Code erstellt werden soll. Die einfachste Dockerfile zur Bereitstellung einer Textklassifikations-REST-API würde wahrscheinlich Anweisungen enthalten, um den Anwendungscode und die Modellgewichte einzuschließen, Python-Pakete im Image zu installieren und den Einstiegspunkt der Anwendung zu definieren. Die Details zum Erstellen von Docker-Images gehen über den Rahmen dieses Blogbeitrags hinaus, Sie können weitere Informationen in diesem Blogbeitrag oder direkt in der Docker-Dokumentation finden. Hier ist dennoch ein Beispiel für eine einfache Dockerfile für die REST-API, die wir bereitstellen:

# Use python 3.11 slim as a base image
FROM python:3.11-slim as app
# Set the working directory inside the image to /app
WORKDIR /app
# Copy the application requirements file to the container
COPY requirements.txt requirements.txt
# Install the application requirements
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application source code to the container
COPY . /app
# Start the application when the container starts
ENTRYPOINT ["python", "app.py"]

Sobald Sie das Docker-Image mit Ihrem Dienst erstellt haben, ist die Bereitstellung auf einem entfernten Server einfach. Das Image muss auf den Server hochgeladen und mit dem Befehl gestartet werden:

docker run image_name

Einen geeigneten Host für die Anwendung finden


Lassen Sie uns nun die Frage erneut aufgreifen, wo ein geeigneter Computer zur Ausführung der containerisierten Modelldienst-API gefunden werden kann. Dies ist eine sehr praktische Frage, und obwohl die Antwort im Wesentlichen "kaufen oder mieten" lautet, ist die Vielfalt der verfügbaren Optionen umfangreich. Eine Möglichkeit, die Compute-Infrastruktur zu kategorisieren, besteht darin, sie auf einer Skala von Anpassung zu Einfachheit zu platzieren. Die Intuition hinter dieser Skala ist, dass je mehr Flexibilität und Kontrolle Sie über die Serverkonfiguration haben, desto mehr Einrichtungsarbeit müssen Sie manuell erledigen, und umgekehrt.

Am extremsten Ende des Anpassungsspektrums befindet sich die sogenannte On-Premise-Architektur, was im Wesentlichen bedeutet, dass Sie Ihren eigenen physischen Computer oder eine Gruppe von Computern kaufen und warten. In diesem Fall sind Sie frei, die genauen CPUs, GPUs, RAM-, Festplattenkonfigurationen und andere Hardwareoptionen sowie Softwareoptionen wie das Betriebssystem auszuwählen. Sie müssen sich jedoch auch um Netzwerke, Speicherplatz, Zugriffsverwaltung und viele andere Details selbst kümmern.

Einen Schritt weiter in Richtung Einfachheit beginnt der Bereich des Cloud-Computing. Im Cloud-Computing-Paradigma verwaltet ein Cloud-Anbieter seine On-Premise-Architektur und ermöglicht es Kunden, diese gegen eine Gebühr zu nutzen. Der Markt für Cloud-Computing ist riesig, wobei die beliebtesten Anbieter Amazon Web Services, Microsoft Azure und Google Cloud Platform sind.

Typischerweise ist das anpassungsfähigste Angebot im Cloud-Computing Infrastructure-as-a-Service (IaaS), bei dem eine virtuelle Maschine bereitgestellt wird. Eine virtuelle Maschine kann als ein Computer mit vordefinierter Hardware und eigenem Betriebssystem betrachtet werden, auf die beispielsweise über SSH zugegriffen werden kann. Diese Lösung nimmt Ihnen als Entwickler einige Last ab, aber Sie müssen immer noch die erforderlichen OS-Pakete installieren und den Speicherplatz verwalten.

Eine einfachere, aber beliebte Lösung ist Container-as-a-Service (CaaS), was bedeutet, dass der Cloud-Anbieter Ihren Docker-Container ausführt. In diesem Szenario müssen Sie sich nur um den Aufbau des korrekten Images kümmern und der Rest wird erledigt. Andererseits haben Sie nicht die Flexibilität, sich beim Server anzumelden und ein beliebiges Programm auszuführen.

Ein noch weniger anpassbares Cloud-Computing-Modell ist Function-as-a-Service (FaaS). Wenn Sie sich für ein FaaS-Angebot entscheiden, sind Sie nur für die Implementierung eines bestimmten Stücks Logik als Funktion verantwortlich, die in einer Programmiersprache Ihrer Wahl geschrieben ist. Der Cloud-Anbieter führt diese Funktion dann mit den bereitgestellten Argumenten aus, wenn das Trigger-Ereignis eintritt.

Dieser Abschnitt kratzt nur an der Oberfläche des Cloud-Computings, dessen Möglichkeiten und wie es Ihnen hilft, Ihre Anwendungen an den Kunden zu liefern. Für einen tiefen Einblick in das Thema sollten Sie direkt die Dokumentation eines Cloud-Anbieters Ihrer Wahl konsultieren.

Als Datenwissenschaftler möchten Sie wahrscheinlich keine Infrastruktur verwalten und Systemadministrationsaufgaben übernehmen, daher sind On-Premise- und IaaS-Ansätze zur Infrastruktur nicht wünschenswert. Andererseits würde der Function-as-a-Service-Ansatz erfordern, das Modell jedes Mal zu laden, wenn eine Anfrage vom Kunden eintrifft, was zu suboptimaler Ressourcennutzung und langen Antwortzeiten führen könnte, wenn das Modell groß ist. Das bedeutet, dass in unserem Fall der Container-as-a-Service-Ansatz das am besten passende Cloud-Computing-Framework zu sein scheint.


Bereitstellung der containerisierten API auf Cloud Run


Bei dida mögen wir Google Cloud Platform als Cloud-Anbieter. Und im GCP heißt das Container-as-a-Service-Tool Cloud Run. Angenommen, Sie haben die REST-API für Ihr Modell implementiert, eine Dockerfile erstellt und ein Konto auf Google Cloud eingerichtet, hier sind die erforderlichen Schritte, um ein Modell auf Cloud Run bereitzustellen:

  1. Erstellen Sie lokal und taggen Sie ein Docker-Image mit Ihrer Anwendung. Das Taggen eines Images bedeutet nur, dass Sie ihm einen eindeutigen Namen geben, indem Sie docker build --tag my-tag . ausführen.

  2. Melden Sie sich beim GCP-Artifact-Registry an und pushen Sie Ihr Image mit docker push my-tag. Die Artifact-Registry ist eine Bibliothek von Images, die Sie in GCP pflegen.

  3. Öffnen Sie das Cloud Run-Dashboard in der Google Cloud-Konsole und erstellen Sie einen neuen Dienst. Geben Sie den Imagenamen, den Servicenamen sowie die minimale und maximale Anzahl der Instanzen an.

  4. Sobald der Container auf Cloud Run bereitgestellt ist, kann jeder auf die Vorhersagen Ihres Modells zugreifen, indem er HTTP-Anfragen an die Dienst-URL sendet!

Die minimale und maximale Anzahl der Instanzen sind Teil einer großartigen Out-of-the-Box-Funktion der Cloud-Anbieter: Auto-Scaling. Wenn Ihr Modell erfolgreich und populär wird, könnte es passieren, dass viele Leute gleichzeitig darauf zugreifen möchten. In diesem Fall wird die Last auf dem Server zu hoch und er könnte langsamer werden oder sogar abstürzen. Eine mögliche Lösung besteht darin, einen zweiten identischen Server zu starten, der das gleiche Image auf separater Hardware ausführt und die Hälfte der eingehenden Anfragen verarbeitet, ähnlich wie eine zweite Kasse im Supermarkt geöffnet wird, wenn die Schlange zu lang wird. Wenn andererseits der Server keine Anfragen erhält, vielleicht nachts, ist es möglich, einige der Instanzen herunterzufahren, um die Rechenressourcen zu sparen. Cloud Run Auto-Scaling macht dies möglich; Sie müssen nur die minimale zulässige Anzahl von laufenden Instanzen und die maximale Anzahl von Instanzen angeben, die bei Spitzenbelastung verfügbar sind.


Fazit


Wenn Sie darauf abzielen, reale Probleme mit Machine-Learning-Algorithmen zu lösen, sollten Sie immer das Endziel im Auge behalten: eine Wirkung dort zu erzielen, wo es darauf ankommt. Und in vielen Fällen bedeutet dies, Ihr Modell in bestehende digitale Workflows einzubetten, eine zugängliche Schnittstelle für Vorhersagen bereitzustellen und es schließlich online bereitzustellen. Hoffentlich hat Ihnen dieses Tutorial ein grundlegendes Verständnis dafür vermittelt, was es braucht, um die Vorhersagen Ihres ML-Modells den Benutzern zugänglich zu machen.

Seien Sie sich bewusst, dass dieser Beitrag kein Schritt-für-Schritt-Rezept ist, dem Sie strikt in Ihrem Projekt folgen sollten. Stattdessen haben wir nur versucht, die wesentlichsten Konzepte anhand eines Beispielmodells zu erläutern. Die Bereitstellung eines Modells ist Teil eines weiten und dynamischen Bereichs des MLOps, und es gibt immer etwas Neues zu lernen, wenn es darum geht, Modelle in Produktion zu bringen oder zu warten.