Zum Hauptinhalt springen

Serverless Data Science auf AWS

Was macht "Serverless" für Data Science interessant?

Serverless stellt als „Function as a Service“ das höchste Abstraktionslevel der XaaS-Familie dar. Im Kern bedeutet das, dass der Benutzer sämtliche Aufgaben, die mit dem Betrieb von Infrastruktur zusammenhängen, an den Cloud-Provider abgibt. Sämtliche Fragen der Bereitstellung, der Wartung oder der Skalierung von Servern treten damit in den Hintergrund.

Der größte Vorteil dieses Ansatzes ist, dass der Benutzer ausschließlich für das Aufrufen der Funktionen bezahlt (s. u. für mehr Details zum Preismodell). Falls der entsprechende Code nur sporadisch genutzt wird, entstehen dadurch große Einsparpotenziale.

Aus einer Data-Science-Perspektive heraus gibt es mehrere Use Cases, die von einem Serverless-Ansatz profitieren können. Allgemein formuliert, liegt die größte Stärke des Ansatzes im On-Demand-Bereich. Beispielhaft können hier von Dateien getriggerte Pipelines oder von APIs getriggerte Vorhersageanfragen genannt werden. Unten demonstriere ich diesen Ansatz mit einem On-Demand-Beispiel für Social-Media-Analysen zu einem bestimmten Suchbegriff.

Sämtliche Cloud-Anbieter haben FaaS in ihr Ökosystem integriert. Um das Beispiel greifbarer zu machen, nutze ich AWS und seine Lambda-Funktion, aber die jeweils beste Wahl hängt stark vom Use Case ab.

AWS Lambda als zentraler Baustein

AWS führte die Lambda-Funktion bereits 2014 ein und erweitert seitdem konsequent den Funktionsumfang. Zu diesem Zeitpunkt unterstützt sie Node.js, Python, Ruby, Go und C#. Lambda-Funktionen bestehen aus zwei Hauptteilen:

  1. Die Funktion selbst, d. h. der auszuführende Code.
  2. Sogenannte „Layers“, die dazu genutzt werden können, zusätzliche Funktionalitäten, z. B. Python Packages, verfügbar zu machen.

Die Kosten für die Benutzung werden von drei Parametern getrieben:

  1. Die Anzahl der Ausführungen pro Monat.
  2. Der zugewiesene Speicher.
  3. Die Ausführungszeit in Millisekunden.

Beispielsweise kostet es nur $2,51 pro Monat, um eine Funktion 1.000-mal täglich aufzurufen, die 512 MB Speicher benötigt und ungefähr zehn Sekunden läuft. Die Ausführungszeit ist dabei der größte Kostentreiber. Das ist auch der Grund, warum Lambda-Funktionen besonders für kleine und schnelle Codeteile vorteilhaft sind. Eine höhere Anzahl von Aufrufen stellt kein großes Problem dar, aber eine längere Ausführungszeit kann schnell durchschlagen. Um Beispielrechnungen durchzuführen, hat AWS hier einen Rechner bereitgestellt.

Die Liste an AWS-Services, die Lambda-Funktionen starten bzw. ihre Ergebnisse empfangen können, ist lang. Für Data-Science-Anwendungen sehe ich vor allem zwei Haupttrigger. Zum einen Trigger, die mit dem Dateisystem (S3) zusammenhängen. Diese Trigger können ausgelöst werden, wenn beispielsweise eine neue Datei abgespeichert wird. Zum anderen sind die Möglichkeiten in Kombination mit dem AWS API Gateway schier grenzenlos. Dieses Setup findet sich vor allem im Bereich von On-Demand Analytics.

Ähnlich flexibel stellen sich die möglichen Empfänger dar. Lambda-Funktionen können beispielsweise ihre Ergebnisse in dafür vorgesehene S3-Buckets schreiben oder sie über das API-Gateway nach außen verfügbar machen. Genauso einfach können Benachrichtigungsdienste wie SNS oder SES angesteuert werden.

Wichtig zu betonen ist, dass zudem jede Kombination an Triggern und Empfängern denkbar ist. So einfach die Konfigurationen auch sind, müssen dabei aber immer auch die zusätzlichen Abhängigkeiten und die steigende Komplexität berücksichtigt werden.

Beispiel – Sentiment-Analyse von Tweets

Nun zu einem konkreten Beispiel dafür, wie Lambda-Funktionen für Data-Science-Zwecke eingesetzt werden können. Ich habe ein Beispiel aus dem Bereich On-Demand Analytics gewählt, aber es gibt weit mehr mögliche Anwendungsfälle für solch einen Ansatz.

Mein Beispiel wird vier verschiedene Dinge tun:

  1. Es wird einen Suchbegriff als Key-Value Pair entgegennehmen (eine Aufgabe, die im kompletten Beispiel das API Gateway leisten würde).
  2. Es wird die Twitter-API um Tweets zu diesem Suchbegriff bitten.
  3. Es wird die Sentiments der gesammelten Tweets analysieren.
  4. Es wird Key-Value Pairs mit dem Anteil positiver, neutraler und negativer Tweets für den Suchbegriff zurückspielen. Diese Daten könnten dann wiederum von einem API Gateway weiterverwendet werden.

lambda-funktion

Abbildung 1: Aufgaben, die die beispielhafte Lambda-Funktion erfüllt

Um solch eine Lambda-Funktion zu implementieren, müssen wir drei Schritte durchführen:

  1. Schreiben des notwendigen Python-Codes.
  2. Erzeugen eines Layers, der die notwendigen Module bereitstellt.
  3. Testen der Funktion mit verschiedenen Suchbegriffen, um die Funktionalität und Laufzeit evaluieren zu können.

Der dritte Schritt ermöglicht eine Kostenschätzung, die dann zur finalen Bewertung herangezogen werden kann.

Implementierung

Der Python-Code für diese Lambda-Funktion sieht so aus:
https://gist.github.com/timo-boehm/598e9f7ae5231f889a197af96be48787

import re
import tweepy
from textblob import TextBlob


def lambda_function(search_term):
    
    # Details for connection
    auth = tweepy.OAuthHandler(consumer_key="XXXX",
                               consumer_secret="XXXX")

    auth.set_access_token(key="XXXX",
                          secret="XXXX")
    
    # Connect to API and collect results
    api = tweepy.API(auth)
    api_output = api.search(q=search_term, count=500)
    
    # Prepare tweets for analysis
    def clean_tweet(tweet):
        return re.sub("(@[\w]*|(https:[\S]*)|([,.;\\n'\"()]))", "", tweet).strip()
    
    tweet_list = [t.text for t in api_output]
    clean_tweets = [clean_tweet(t) for t in tweet_list]
    unique_tweets = set(clean_tweets)
    
    # Calculate sentiments for all tweets
    sentiments = [TextBlob(t).sentiment.polarity for t in unique_tweets]
    
    # Aggregate sentiments in one dictionary
    aggregated_sentiments = {"positive": len([s for s in sentiments if s > 0]) / len(sentiments),
                             "neutral":  len([s for s in sentiments if s == 0]) / len(sentiments),
                             "negative": len([s for s in sentiments if s < 0]) / len(sentiments)}
    
    return aggregated_sentiments


Um das Beispiel einfach zu halten, habe ich die notwendigen Schlüssel für die Twitter-API fest programmiert. Das sollte in einem tatsächlichen Use Case offensichtlich anders gelöst werden. Ich habe außerdem die Anzahl notwendiger Packages auf ein Minimum reduziert. Diese Entscheidung ist vom zweiten Baustein motiviert: Layers.

Es gibt verschiedene Wege, Layers auf AWS zur Verfügung zu stellen. Der einfachste Weg ist der Upload einer Zip-Datei, die die notwendige Ordnerstruktur beinhaltet („\python\lib\pythonX.X\site-packages\“). Wichtig dabei: Je kleiner die Zip-Datei, desto performanter die Lambda-Funktionen. Da die Ausführungszeit der größte Kostentreiber ist, lohnt es sich hier also, so sparsam wie möglich zu sein.

Nun, da die notwendigen Bausteine platziert sind, können wir das Beispiel evaluieren. Im Schnitt beträgt die Laufzeit ungefähr 2,5 Sekunden. Würde diese Funktion täglich 10.000 Anfragen ausführen, würden die Kosten pro Monat also nur $3 betragen! Die Kosten-Nutzen-Rechnung ist damit unschlagbar.

Data-Science-Potenziale im Serverless Framework

Lambda-Funktionen (und ihre Entsprechungen bei anderen Cloud-Anbietern) taugen nicht für alle Data-Science-Anwendungen. Zudem kann die Leichtigkeit, mit der sie sich einrichten lassen, Fluch und Segen zugleich sein. Der Segen liegt in der Geschwindigkeit, mit der experimentiert werden kann. Der Fluch liegt in dem Potenzial für „Quick Fixes“, die schnell zu Unübersichtlichkeit und Qualitätsproblemen führen können. Jeder Anwender muss deshalb den Einsatz von Lambda-Funktionen bewusst planen. Das gilt besonders für die Operationen, die einer Lambda-Funktion innerhalb der Cloud-Umgebung zugänglich sind.

In der Summe überwiegt aber das große Potenzial. Beispielsweise können trainierte Machine-Learning-Modelle als Objekte in S3 hinterlegt werden, und dann kann die kostengünstige Lambda-Funktion mit dem Berechnen der Vorhersagen betraut werden. Kombiniert mit anderen AWS-Services, z. B. Step-Functions, können sie zudem einfach in Datenverarbeitungsprozesse integriert werden, die kleinere Machine-Learning-Bausteine enthalten.

Wie viele andere Begriffe und Konzepte ist auch „Serverless“ nicht die Lösung aller Probleme. Trotzdem ist es ein mächtiges Tool, das seinen Platz im Data-Science-Werkzeugkasten sicher finden wird.

Dr. Michael Allgöwer
Dein Ansprechpartner
Dr. Michael Allgöwer
Management Consultant
Machine Learning ist Michaels langjährige Spielwiese. Michael ist überzeugt, dass gutes Machine Learning eine Menge Branchenverständnis voraussetzt, und er liebt es, sich dieses Verständnis immer wieder zu erarbeiten. Sein neuestes Lieblingsthema ist Reinforcement Learning.
#MachineLearning #ReinforcementLearning #HumanIntelligence