Softwareentwickler kennen sich mit Datentypen aus. Ein Datentyp für eine Variable in einer Programmiersprache definiert die gültigen Operationen für diese Variable – ungültige Operationen verursachen entweder Compiletime- oder Runtime-Fehler. Aber wie erklärt man einem Softwareentwickler, der neu im Bereich Machine Learning ist, was ein Featuretyp ist, wenn Mainstream-Programmiersprache wie z.B. Python keine native Unterstützung dafür bieten? In diesem Beitrag definieren wir das Konzept von Featuretypen und erörtern, was ein Featuretyp im Kontext des Hopsworks Feature Store bedeutet.
Frisch gebackene Programmierer sind mit Strings, Int und Booleans vertraut. Programmiersprachen unterstützen Datentypen auf Sprachebene. Wenn Sie jedoch mit der Programmierung mit Frameworks für Machine Learning (ML) beginnen, bedeutet die fehlende Unterstützung für Featuretypen auf Sprachebene, dass es nicht denselben klar definierten Satz von Operationen auf kategoriale Variablen, numerische Variablen und Embeddings gibt. In Python können Sie beispielsweise ein Framework für Machine Learning wie Scikit-Learn, TensorFlow, XGBoost oder PyTorch verwenden, und in jedem Framework gibt es einen anderen Satz gültiger Operationen für diese verschiedenen Featuretypen.
Der Feature Store ist eine vereinheitlichte Datenschicht für ML-Frameworks, daher erfordert die Unterstützung von Featuretypen in Feature Stores klare und eindeutige Operationen, die von so möglichst vielen ML-Frameworks auf hoher Ebene unterstützt werden.
Wir können damit beginnen zu definieren, was ein Feature (aus Sicht von Data Engineers) ist. Ein Feature ist einfach eine Variable, die eine Eingabe für ein maschinelles Lernmodell darstellt. Ein Feature Store hilft beim Berechnen und Speichern von Features. Features werden in der Regel in Batches – DataFrames – verarbeitet, die sowohl für Modelltrainings als auch für Batch-Vorhersagen genutzt werden können.
Wenn Sie eine Online-Anwendung haben, die Vorhersagen mit einem ML-Modell trifft, benötigen Sie normalerweise eine Zeile (oder einen Vektor) von Merkmalen. Um beispielsweise einem Benutzer eine Empfehlung für Ihre Einzelhandels-Website zu geben, möchten Sie möglicherweise Merkmale basierend auf seiner aktuellen Session (besuchte Seiten, Artikel im Warenkorb), aber auch historische Merkmale über frühere Besuche und Kontextmerkmale – z.B. Produktinformationen – berechnen. Ihre Webanwendung ist wahrscheinlich zustandslos, und die Verlaufs- und Kontextfunktionen wurden vorberechnet und im Feature Store gespeichert. Ihre zustandslose Webanwendung ruft sie bei Bedarf als Zeilen (Merkmalsvektoren) ab, um eine Vorhersage zu treffen. In Python ML-Frameworks wird ein Merkmalsvektor vom Modell verwendet, um eine Vorhersage zu treffen. Oft ist dies ein NumPy-Array oder ein n-dimensionaler Tensor.
Features werden in Ihrem Feature Store als tabellarische Daten in einem Zeilen-/Spalten-Layout gespeichert, in dem die Spalten die Features sind und sich die Zeilen aus Feature-Werte und einem Entitätsschlüssel (oder Primärschlüssel) zusammensetzen, sowie einer optionalen event_time-Spalte, die angibt, zu welchem Zeitpunkt die Feature-Werte erfasst wurden.
In der obigen Tabelle enthält jedes Merkmal entweder quantitative oder qualitative Informationen. Quantitative Daten sind numerisch. Zum Beispiel die Niederschlagsmenge oder die Temperatur. Qualitative Daten sind diskrete Werte, die einer endliche Anzahl bekannter Werte haben, wie beispielsweise weather_description in der obigen Tabelle.
Manchmal wandeln Sie quantitative Daten in qualitative Daten um, damit das ML-Modell einfache Muster in den Daten erlernen kann. Sie könnten beispielsweise entscheiden, dass die Funktionswerte für Niederschlag und Temperatur sparse sind und Sie nicht über genügend Trainingsdaten verfügen, sodass Sie diese lieber in eine kategoriale Variablen umwandeln. Beispielsweise können Ihre Trainingsbeispiele unterschiedliche Werte für Temperatur und Niederschlag aufweisen, was es wird für Ihr Modell schwieriger macht, Muster in Ihren Daten zu lernen. Wenn Sie den Niederschlag jedoch in Kategorien umwandeln – [trocken, feucht, nass, sintflutartig], kann Ihr Modell leichter vorhersagen, ob die Niederschlagsmenge in eine dieser Kategorien fallen wird.
Eine Taxonomie von Merkmalstypen ist in der folgenden Abbildung dargestellt, wobei ein Merkmal eine diskrete Variable (kategorisch), eine kontinuierliche Variable (numerisch) oder ein Array (viele Werte) sein kann. Genau wie ein Datentyp verfügt jeder Featuretyp über einen Satz gültiger Transformationen. Beispielsweise können Sie eine numerische Variable (aber keine kategoriale Variable) normalisieren, und Sie können eine kategoriale Variable (aber keine numerische Variable) One-Hot-Codieren. Bei Arrays können Sie den Maximal-, Minimal- oder Durchschnittswert aus einer Werteliste zurückgeben (vorausgesetzt, diese Werte sind numerisch). Der Featuretyp hilft Ihnen zu verstehen, welche Aggregationen und Transformationen Sie auf eine Variable anwenden können.
Kategoriale Merkmale basieren auf diskreten Daten. Wenn ein kategoriales Merkmal keine natürliche Ordnung hat (wie das Wettermerkmal aus der obigen Tabelle), nennen wir es eine nominale Variable. Eine übliche Operation bei nominalen Variablen besteht darin, die Häufigkeit des Auftretens ihrer verschiedenen diskreten Werte zu zählen, oft über Zeitfenster. Sie können auch den „Modus“ oder den häufigsten diskreten Wert in Ihrer Nominalvariablen identifizieren, aber Sie können keinen Median für eine Nominalvariable berechnen.
Wenn das kategoriale Merkmal jedoch eine natürliche Ordnung hat, wird es als ordinale Variable bezeichnet. Beispielsweise kann unser transformiertes Niederschlagsfeature von vorher (trocken, feucht, nass, sintflutartig) als ordinale Variable betrachtet werden, da Sie die Werte basierend auf der Niederschlagsmenge ordnen können. Bei ordinalen Variablen hat die Differenz zwischen zwei beliebigen Werten jedoch keine mathematische Bedeutung. Beispielsweise ergibt das Hinzufügen von „trocken“ zu „feucht“ keinen mathematischen Sinn. Der Median kann oft für nominale Variablen berechnet werden. Zum Beispiel ist „feucht“ der mittlere Niederschlag für Irland.
Eine numerische Variable beschreibt quantitative Daten. Numerische Variablen ähneln ordinalen Variablen, außer dass bei numerischen Variablen die Unterschiede zwischen Werten eine konsistente Bedeutung haben. Im Gegensatz zu kategorialen Variablen können Sie im Allgemeinen numerische Variablen addieren und subtrahieren, und die Ergebnisse haben eine Bedeutung. Numerische Merkmale werden über eine Skala gemessen, wobei die Skala entweder endlich oder unendlich sein kann, und Sie können auch Maße der zentralen Tendenz (Mittelwert, Median, Modus) sowie deren Variabilitätsmaße (Varianz und Standardabweichung) berechnen. Dies ist beispielsweise hilfreich, um fehlende Werte durch das arithmetische Mittel oder den Median der numerischen Variablen zu ersetzen. Numerische Variablen können weiter in zwei verschiedene Typen unterteilt werden: Intervall- und Verhältnisvariablen.
Eine Intervallvariable ist eine numerische Variable, die nicht das Konzept einer wahren Null hat. Das heißt, für unsere Funktion steht keine „Null“-Pegelmessung zur Verfügung. Beispielsweise könnte eine Intervallvariable ein weather_score (auf einer Skala von 1 bis 5) sein. Wir können nützliche Statistiken berechnen, wie den mittleren Wetterwert, aber es gibt keine Vorstellung von einer echten Null – ein Nichtvorhandensein der Sache, die Sie zu messen versuchen.
Eine Verhältnisvariable ist eine numerische Variable mit einem sinnvollen Nullwert, z. B. die Temperaturfunktion oben. Intervallvariablen haben keine echte Null, daher können Sie Werte nur zusammen mit Bedeutung addieren und subtrahieren. Verhältnisvariablen können dank einer echten Null auch dividiert und multipliziert werden, was zu aussagekräftigen Ergebnissen führt. Wenn wir beispielsweise sagen, dass sich der Niederschlag pro Monat von 100 mm verdoppelt hat, wissen wir, dass das Ergebnis 200 mm ist, weil die Verdopplung relativ zu Null ist.
Unsere Taxonomie von Merkmalstypen ist jedoch nicht vollständig. Die letzte Feature-Klasse, die wir in Feature-Stores anders handhaben, ist ein Array von Variablen. Während Arrays traditionell nicht als Featuretyp betrachtet werden, ist dies eine Reihe gültiger mathematischer Operationen und Transformationen, die Sie an ihnen durchführen können.
Ein Feature Store ist nützlicher, wenn er native Unterstützung für das Speichern von Arrays von Werten bietet. Das Array kann alles sein, von einem (ungeordneten) Vektor aus Gleitkommazahlen bis hin zu einer (geordneten) Liste von Werten (mehrere kategoriale Variablen).
Ein Embedding ist auch ein Array - ein Array von Zahlen, oft Floats. Formaler ausgedrückt ist eine Embedding die Abbildung eines diskreten Satzes auf einen Vektorraum, der als Embedding-Raum bezeichnet wird. Das heißt, ein Embedding ist eine niederdimensionale Darstellung einiger Eingangs-Merkmale, die unter Verwendung eines Embedding-Algorithmus berechnet wird. In der obigen Tabelle gibt es zum Beispiel eine Funktion namens weather_photo_embed. Wenn Sie Wetterfotos haben, transformiert und komprimiert ein Embedding-Algorithmus die Fotos in ein kleines Array aus Gleitkommazahlen mit fester Länge - die Embedding-Funktion. Embeddings können für die Ähnlichkeitssuche verwendet werden. Bei unseren Wetterfotos könnten Sie Embeddings möglicherweise nutzen, um ein Wetter zu finden, das dem Wetter auf dem Foto ähnlich ist. Embeddings können auch verwendet werden, um Modelle zu trainieren, die auf einer kategorialen Variablen mit geringer Dichte basieren. Das Embedding kann Ihre sparse kategoriale Variable komprimieren, sodass das Modell von einem niederdimensionalen Merkmal lernen kann. Ein wichtiger Hyperparameter von Embeddings ist ihre Länge – wird es 4 oder 16 oder 32 oder 200 Floats lang sein?
Ein Feature-Store kann auch eine Liste von Feature-Werten in einem einzelnen Feature speichern, um den Entwicklungsaufwand zu reduzieren oder die Speicherkosten zu optimieren. Doordash unterstützt bspw. Listenfunktionen, um Features zu komprimieren und dadurch Speicherkosten im Feature Store zu reduzieren. Ein weiterer beispielhafter Anwendungsfall für eine Liste als Featuretyp ist das Ersetzen von 10 separaten Features für 10 Standorte mit dem besten Wetter von gestern, durch ein einzelnes Feature, das alle 10 Standorte enthält. Verschiedene Benutzer können denn Listenfunktion auf unterschiedliche Weise nutzen – z.B. um den Top-Standort oder das durchschnittliche Wetter an den Top-10-Standorten zu berechnen.
Obwohl es sich nicht speziell um einen Featuretyp handelt, kann es auch vorkommen, dass einige Features, die zum Trainieren eines Modells verwendet werden, keine Vorhersagekraft haben. Solche Merkmale sind irrelevante Merkmale und sollten identifiziert und dann aus den Trainingsdaten entfernt werden, da sie das Training verlangsamen, die Konvergenz von Modellen erschweren und Modelle unnötig vergrößern. Der Feature Store kann Ihnen dabei helfen, nutzlose Features zu identifizieren, indem er beispielsweise Trainingsdaten analysiert und stark korrelierte (redundante) Features identifiziert werden.
Angesichts der hier definierten unterschiedlichen Arten von Features ist es interessant festzustellen, dass Features in einem Feature Store in überwachten, nicht überwachten und selbst überwachten ML-Modellen wiederverwendet werden können. Bei überwachtem ML kann ein Label ein Feature im Feature Store sein oder aus einem externen Datenspeicher stammen. Das heißt, das Label aus einem Modell könnte als Merkmal in einem anderen Modell verwendet werden. Selbstüberwachte Trainingsdaten können ein großes Volumen haben, und anstatt viele Daten in den Feature Store zu kopieren, unterstützen einige Feature Stores externe Tabellen, in denen die Features im Feature Store registriert, aber in verschiedenen externen Quellen (wie z.B. Parquet-Dateien in einem Data Lake oder Tabellen in einem Data Warehouse wie Snowflake, BigQuery oder Redshift).
An dieser Stelle ist es wichtig zu beachten, dass die hier definierten Featuretypen abstrakt sind und Sie mit konkreten Datentypen arbeiten, wenn Sie mit Numpy-Arrays, Pandas- oder Spark-Datenrahmen oder SQL-Abfragen programmieren. Die von Ihrem Feature-Store unterstützten Datentypen sollten eng mit den Frameworks übereinstimmen, die Sie für das Feature-Engineering verwenden. Alle Datentypen müssen in numerische Daten konvertiert werden, bevor sie als Trainingsdaten oder Inferenzdaten weitergegeben werden. Modelle für Machine Learning verwenden Zahlen als Eingabe und geben eine Zahl als Vorhersage heraus. Featuretypen definieren den Satz gültiger Transformationsfunktionen, die auf einen Datentyp angewendet werden können. Ohne den Featuretyp kann der Feature-Store nicht immer wissen, welche gültigen Transformationen auf ein Feature angewendet werden können. Dann bleibt es Ihnen als Programmierer überlassen, zu entscheiden, wie Sie das Merkmal in ein numerisches Format umwandeln, das von Ihrem Modell akzeptiert wird.
Wie bereits erwähnt, wissen Sie vielleicht, dass Sie bei einem ordinalen (kategorialen) Merkmal Zählungen über seine Werte berechnen können, während Sie bei einer numerischen Variablen deskriptive Statistiken darüber berechnen können (Mittelwert, Min., Max., Standardabweichung). ). Wenn Sie in Ihrem Feature Store Features mit einem bekannten Featuretyp definiert haben, kann der Feature Store dabei helfen, Hinweise darauf zu geben, welche Arten von Aggregationen über Features berechnet werden können. Wenn Sie diese Daten nur in einem Data Warehouse mit Datentypinformationen haben, ist es schwieriger, Hinweise auf sinnvolle Aggregationen zu geben.
In Hopsworks schreiben Sie Features in Feature Groups (Tabellen in denen die Features gespeichert werden) und Sie lesen Features aus Feature Views. Ein Feature View ist eine logische Ansicht über Features, die in Feature Groups gespeichert sind, und ein Feature View enthält normalerweise die Features, die von einem bestimmten Modell verwendet werden. Auf diese Weise ermöglichen Feature Views die Wiederverwendung von Features aus verschiedenen Feature Groups in vielen verschiedenen Modellen.
Transformationen können im Feature-Engineering vor dem Speichern in Feature Groups durchgeführt werden, wodurch die Latenz zum Lesen des Features reduziert wird, aber das Feature in verschiedenen Modellen weniger wiederverwendbar wird. Alternativ können sie auf Feature Views angewendet werden, wobei eine Online-Transformation des Features während des Lesens erforderlich ist, jedoch die Features in verschiedenen Modellen besser wiederverwendbar werden.
Der Feature View ist eine logische Ansicht über (oder eine Schnittstelle zu) einem Satz von Features, die aus verschiedenen Feature Groups stammen können.
In der obigen Abbildung sehen wir, dass die Features für einen Feature View aus den beiden folgenden Feature Groups zusammengefügt werden: weather_feature_group und surf_feature_group. Sie können auch sehen, dass Features im Feature View nicht nur den Featuretyp von ihren Feature Groups erben, sondern auch, ob es sich um den Primärschlüssel und/oder die event_time handelt. Die Abbildung enthält auch Transformationsfunktionen, die auf einzelne Features angewendet werden, nachdem sie aus Feature Groups gelesen wurden. Transformationsfunktionen sind Teil der Featuretypen, die in der Feature View enthalten sind. Die Transformationsfunktionen werden sowohl (1) beim Lesen von Features als DataFrames mithilfe der Offline-API (zum Erstellen von Trainingsdaten oder für Batch-Scoring) als auch (2) beim Lesen von Features als Feature-Vektoren mithilfe der Online-API angewendet. Das heißt, ein Feature in einem Feature View wird nicht nur durch seinen Datentyp (int, string usw.) oder seinen Featuretyp (kategorisch, numerisch, Embedding) definiert, sondern auch durch jede darauf angewendete Transformationsfunktion. Der Feature View stellt sicher, dass die Transformationsfunktion konsistent angewendet wird, wenn entweder Daten-Batches für das Training oder einzelne Zeilen (Vektoren) für Onlinevorhersagen erstellt werden. Dies löst das Problem der Training-Serving-Skew, bei dem Transformationsfunktionen, die zum Erstellen von Trainingsdaten und für die Online-Verarbeitung von Merkmalsvektoren verwendet werden, unterschiedliche Implementierungen haben können, was zu schwer diagnostizierbaren Modellleistungsfehlern führt.
Featuretypen sind eine nützliche Erweiterung von Datentypen, um den Satz gültiger Operationen für eine Variable beim maschinellen Lernen zu verstehen. Der Feature Store kann einen Featuretyp verwenden, um gültige Transformationen (Normalisierung, One-Hot-Codierung usw.) für Features zu identifizieren oder eine adäquate Darstellung von Feature-Metriken zu erzeugen. Embeddings sind ein relativ neuer Featuretyp (Arrays), und wir glauben, dass Lehrbuchbeispiele überholt sind, in denen nur zwischen kategorischen und numerischen Feature unterschieden wird. Embeddings sollten, wie es in Feature-Stores wie Hopsworks widergespiegelt wird, als First-Class-Citizens.