Kapitel 4. Automatisierung der Datenqualitätsüberwachung mit maschinellem Lernen

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Maschinelles Lernen ist ein statistischer Ansatz, der im Vergleich zu regelbasierten Tests und der Überwachung von Metriken viele Vorteile hat: Er ist skalierbar, kann unbekannte Veränderungen erkennen und ist - auch auf die Gefahr hin, dass er vermenschlicht wird - intelligent. Sie kann aus früheren Eingaben lernen, Kontextinformationen nutzen, um Fehlalarme zu minimieren, und deine Daten im Laufe der Zeit immer besser verstehen.

In den vorherigen Kapiteln haben wir untersucht, wann und wie Automatisierung mit ML für deine Strategie zur Überwachung der Datenqualität sinnvoll ist. Jetzt ist es an der Zeit, den Kernmechanismus zu erforschen: wie du ein Modell trainieren, entwickeln und verwenden kannst, um Datenqualitätsproblemezu erkennen - undsogar Aspekte wie deren Schweregrad und wo sie in deinen Daten auftreten zu erklären.

In diesem Kapitel erklären wir, welcher Ansatz des maschinellen Lernens sich am besten für die Überwachung der Datenqualität eignet und zeigen dir den Algorithmus (eine Reihe von Schritten), mit dem du diesen Ansatz umsetzen kannst. Wir beantworten Fragen wie die, wie viele Daten du abfragen solltest und wie du die Ergebnisse des Modells erklärbar machst. Es ist wichtig zu betonen, dass die hier beschriebenen Schritte nicht zu einem Modell führen, mit dem du reale Daten überwachen kannst. In Kapitel 5 widmen wir uns den praktischen Aspekten der Abstimmung und Prüfung deines Systems, damit es in einem Unternehmen zuverlässig funktioniert.

Anforderungen

Es gibt viele ML-Techniken, die du auf ein bestimmtes Problem anwenden könntest. Um den richtigen Ansatz für deinen Anwendungsfall zu finden, ist es wichtig, die Anforderungen im Voraus zu definieren. Unserer Meinung nach sollte ein Modell zur Überwachung der Datenqualität vier Merkmale aufweisen: Sensitivität, Spezifität, Transparenz und Skalierbarkeit.

Empfindlichkeit

Die Sensitivität ist ein Maß dafür, wie gut ein ML-Modell echte positive Ergebnisse erkennen kann. Um effektiv zu sein, sollte ein Algorithmus in der Lage sein, eine Vielzahl von Datenqualitätsproblemen in realen tabellarischen Daten zu erkennen. Ein guter Richtwert ist die Fähigkeit, Änderungen zu erkennen, die 1 % oder mehr der Datensätze betreffen.

In der Praxis haben wir festgestellt, dass der Versuch, Änderungen zu erkennen, die weniger als 1 % der Datensätze betreffen, ein System hervorbringt, das einfach zu verrauscht ist. Selbst wenn die entdeckten Änderungen statistisch signifikant sind, gibt es zu viele davon, um sie zu sortieren und zu verstehen, vor allem, wenn es sich um eine große Anzahl komplexer Tabellen handelt. Unserer Erfahrung nach handelt es sich bei Änderungen, die 1 % oder mehr der Datensätze betreffen, um signifikante strukturelle Änderungen bei der Datengenerierung oder -umwandlung, die große neue Schocks und Narben verursachen können.

Um Änderungen zu finden, die kleiner als 1 % sind, kannst du entweder deterministische Ansätze verwenden (z. B. Validierungsregeln) oder du kannst die ML auf eine Teilmenge von Daten konzentrieren, indem du das Modell auf einer Ansicht laufen lässt, die nur die wichtigsten Datensätze abfragt.

Eine Social-Media-Plattform könnte zum Beispiel Hunderte verschiedener Arten von Ereignissen in einer einzigen großen Ereignisverarbeitungstabelle erfassen. Wenn du ML auf die gesamte Tabelle anwendest, würdest du grobe Probleme mit dem Format und der Struktur der am häufigsten gesammelten Ereignistypen erkennen. Du könntest das Modell aber auch auf Hunderte von ereignisspezifischen Teilmengen anwenden, wenn du sie alle berücksichtigen möchtest.

Spezifität

Das Gegenstück zur Sensitivität, die Spezifität, gibt an, wie gut das Modell darin ist, keine falsch positiven Alarme auszulösen. Dies ist vor allem bei der Überwachung der Datenqualität wichtig, da eine Ermüdung der Warnmeldungen die Akzeptanz und Wirksamkeit des gesamten Ansatzes gefährden kann.

Normalerweise neigt ein Überwachungssystem aus verschiedenen Gründen dazu, übermäßig zu alarmieren. Ein Grund kann die Saisonabhängigkeit sein: Wenn es in den Daten Muster gibt, die sich täglich, wöchentlich oder jährlich wiederholen, sieht es zwar so aus, als würden sich die Daten ändern, aber sie ändern sich nicht wirklich auf ungewöhnliche oder unerwartete Weise. Der Monitor kann auch verrauscht sein, wenn er nicht in der Lage ist, korrelierende Spalten, die von derselben Datenänderung betroffen sind, zu clustern. Oder er könnte falsch-positive Alarme senden, wenn er eine zu kleine Datenstichprobe überprüft oder die Daten in einem zu kleinen Zeitfenster auswertet. Außerdem gibt es einige Datensätze, die viel "chaotischer" sind als andere. Daher muss der Schwellenwert, wie empfindlich eine Prüfung sein sollte, auf jeden Datensatz abgestimmt werden (und sich möglicherweise im Laufe der Zeit weiterentwickeln).

In Kapitel 5 werden wir untersuchen, wie ein Modell lernen und Saisonalität, Korrelationen und andere Herausforderungen von realen Daten berücksichtigen kann.

Transparenz

Wenn Probleme auftauchen, sollte das Modell transparent sein und den Nutzern helfen, Probleme zu verstehen und ihnen auf den Grund zu gehen. Du denkst vielleicht, dass dies nichts mit dem Modell selbstzu tun hat -schließlich werden alle ausgefallenen Visualisierungen und Ursachenanalysen erst nach der Erkennung eines Datenproblems durchgeführt. Aber deine Möglichkeiten hängen tatsächlich von dem ML-Ansatz ab, den du verwendest. Die Architektur und die Implementierung deines Modells bestimmen, inwieweit du seine Vorhersagen erklären und zuordnen kannst. Einige ML-Funktionen können zum Beispiel die Genauigkeit verbessern, sind aber im Zusammenhang mit der Datenqualität für die Nutzer schwer zu erklären.

Skalierbarkeit

Um täglich auf potenziell Milliarden von Zeilen in einem Data Warehouse zu laufen, muss dein System auch skalieren - in Bezug auf Menschen, Speicherung und Rechenkosten. Es sollte keine Vorabkonfiguration oder Nachjustierung durch Administratoren erfordern, da dies nur eine weitere Form handgeschriebener Regeln wäre, die, wie wir bereits in Kapitel 2 gezeigt haben, keine skalierbare Lösung darstellen. Sie sollte einen minimalen Abfrage-Fußabdruck im Data Warehouse haben und in der Lage sein, schnell auf kostengünstiger Hardware außerhalb des Warehouses ausgeführt zu werden. Diese Einschränkungen werden sich auf viele Aspekte unserer Modellierungsentscheidungen auswirken, und wir werden im Laufe dieses Kapitels Wege aufzeigen, wie wir die Lösung skalierbarer machen können.

Nicht-Anforderungen

Zu definieren, was ein System nicht tun muss, kann genauso nützlich sein wie zu definieren, was es tun sollte. Vielleicht erinnerst du dich aus Kapitel 2, dass ein unüberwachtes ML-Modell nur ein Teil eines Vier-Säulen-Ansatzes zur Datenqualität sein sollte, der auch regelbasierte Tests und die Überwachung von Metriken umfasst. Das liegt daran, dass man nicht erwarten kann, dass die Automatisierung jedes Datenqualitätsproblem löst.

Hier ist eine Liste der Nicht-Anforderungen für unser Modell:

  • Sie muss nicht einzelne fehlerhafte Datensätze identifizieren (dafür sind regelbasierte Tests gedacht: wenn die Daten perfekt sein müssen). Stattdessen erwarten wir, dass sie nach strukturellen Veränderungen in aussagekräftigen Prozentsätzen von Datensätzen sucht.

  • Es ist nicht erforderlich, Daten in Echtzeit zu verarbeiten. Die Echtzeitauswertung eines ML-Modells zur Erkennung von Datenqualität wäre nicht nur schwer zu skalieren, sondern es könnte auch gezwungen sein, einzelne Datensätze auszuwerten, was nicht in unserem Rahmen liegt. Stattdessen erwarten wir, dass es Daten in täglichen oder stündlichen Stapeln auswertet.

  • Wir können nicht erwarten, dass es in der Lage ist, zu erkennen, ob die Daten immer beschädigt waren - so funktioniert ML nicht, denn das Modell muss auf historischen Daten trainiert werden. Wenn diese historischen Daten falsch sind, können wir nichts dagegen tun! Deshalb sollte man sich auf einen ML-Ansatz nur verlassen, wenn es darum geht, neue Veränderungen in den Daten zu erkennen.

  • Wir können nicht erwarten, dass es Daten ohne eine gewisse Vorstellung von Zeit analysiert. Das Modell wird die Daten im Laufe der Zeit verfolgen, um Veränderungen zu erkennen. Wenn die Daten selbst keinen Zeitstempel enthalten, müssen wir andere Methoden entwickeln, um festzustellen, wann die Daten erzeugt wurden (dazu später mehr).

Datenqualitätsüberwachung ist keine Ausreißer-Erkennung

Zum Abschluss unserer Diskussion über die Anforderungen an ein Modell zur Überwachung der Datenqualität sollten wir uns einen Moment Zeit nehmen, um auf eine häufige Verwirrung einzugehen: den Unterschied zwischen Ausreißererkennung und Überwachung der Datenqualität.

Die Erkennung von Ausreißern kann eine nützliche Methode sein, um komplexe Datensätze zu verstehen. Es gibt viele Möglichkeiten, Ausreißer zu identifizieren, aber einer der skalierbarsten und flexibelsten Ansätze ist die Verwendung einer Variante des Random Forest namens Isolation Forest, um Datenzeilen zu identifizieren, die weit vom "Zentrum" einer multivariaten Verteilung entfernt sind, wie in Abbildung 4-1 dargestellt.

An example of using Isolation Forest in scikit-learn to find outlier observations (those points outside of the delineated clusters) (scikit-learn at https://scikit-learn.org/stable/auto_examples/miscellaneous/plot_anomaly_comparison.html#sphx-glr-auto-examples-miscellaneous-plot-anomaly-comparison-py)
Abbildung 4-1. Ein Beispiel für die Verwendung von Isolation Forest in Scikit-learn, um Ausreißer zu finden (Punkte, die außerhalb der abgegrenzten Cluster liegen); aus "Comparing Anomaly Detection Algorithms for Outlier Detection on Toy Datasets", Scikit-learn.

Die Erkennung von Ausreißern kann mit ML durchgeführt werden und versucht, ungewöhnliche Aspekte der Daten herauszufinden. Aber die Ähnlichkeiten mit der Überwachung der Datenqualität enden hier. Schließlich gibt es in jedem Datensatz ungewöhnliche Beobachtungen - selbst eine Normalverteilung hat Extremwerte! Diese Ausreißer können interessant sein (es könnte sich um betrügerische Datensätze oder sehr seltene Ereignisse oder Datenkombinationen handeln), aber sie sind nicht unbedingt ein Problem für die Datenqualität, die mit gleicher Wahrscheinlichkeit häufige oder seltene Datensätze betreffen kann.

Um Probleme mit der Datenqualität zu erkennen, müssen wir wissen, wann es eine plötzliche strukturelle Veränderung in der Verteilung der Daten gibt, die in der Tabelle ankommen. Wir müssen wissen, ob die Datensätze in der Vergangenheit immer mit einer bestimmten Verteilung, einem bestimmten Muster oder einer bestimmten Beziehung auftauchten und sich dies nun plötzlich deutlich verändert hat. Auf der anderen Seite gibt es in jedem Datensatz Ausreißer. Die Erkennung von Ausreißern ist die Lösung eines grundlegend anderen Problems.

ML-Ansatz und Algorithmus

Nachdem wir nun die Anforderungen erläutert haben, stellen wir dir den von uns empfohlenen Ansatz und die Schritte vor, mit denen du ihn umsetzen kannst. Wir wollen nicht behaupten, dass dies der einzige Weg ist, ML zur Erkennung von Datenqualitätsproblemen einzusetzen, aber wir haben noch keinen Ansatz gefunden, der die Anforderungen in der Praxis besser erfüllt. Wie immer steckt der Teufel im Detail. Dinge wie die Entwicklung von Merkmalen und die Abstimmung/Dämpfung von Parametern machen den Unterschied zwischen einer effektiven Implementierung und einer, die bei realen Daten zu viel oder zu wenig Alarm schlägt, aus, wie wir in Kapitel 5 weiter ausführen werden.

Wir wollen ein ML-Modell entwickeln, um unerwartete Veränderungen in unseren Daten zu erkennen, ohne dass ein Mensch die Daten kennzeichnet und uns sagt, was ein Datenqualitätsproblem ist. Das macht diese Art von ML-Problem zu einer unüberwachten Lernaufgabe. Es gibt jedoch ein Merkmal der Daten, das wir wie ein menschliches Etikett verwenden können, und das ist der Zeitpunkt, zu dem die Daten in der Tabelle eingegangen sind.

Darin liegt die wichtigste Erkenntnis dieses Ansatzes. Jeden Tag machen wir einen Schnappschuss von den Daten. Dann versuchen wir jeden Tag, einen Klassifikator zu trainieren, der vorhersagt, ob die Daten von heute sind oder nicht.

Image

Wenn es nichts statistisch Bemerkenswertes an den Daten von heute gibt, dann sollte unser Versuch, einen Klassifikator zu trainieren, fehlschlagen - die Vorhersage, ob die Daten von heute sind oder nicht, sollte eine unmögliche Aufgabe sein, im Grunde ein Münzwurf!

Wenn wir andererseits einen Klassifikator erstellen können, der mit einer gewissen Genauigkeit vorhersagt, ob ein Datensatz von heute stammt, dann können wir ziemlich sicher sein, dass etwas an den Daten von heute ungewöhnlich ist. Denn ein paar zufällige Änderungen in ein paar Datensätzen reichen nicht aus, um ein Modell zu trainieren, das eine Vorhersage in die eine oder andere Richtung macht. Mit dieser Methode können wir sogar sagen, wie signifikant die Veränderung ist, und entsprechende Schwellenwerte festlegen, um eine Ermüdung des Alarms zu vermeiden. Indem wir die Vorhersagen des Modells erläutern, können wir erklären, was höchstwahrscheinlich in den Daten vor sich geht.

Ein Modell kann eine Veränderung erkennen, die signifikant ist, auch wenn diese Veränderung nicht interessant ist. Das offensichtlichste Beispiel dafür ist die Spalte date. Diese Spalte wird sich jeden Tag ändern und stellt daher immer eine dramatische Veränderung in den Daten dar! Wie du mit solchen Fällen umgehst, erfährst du in Kapitel 5. Die andere Art von Änderung, die vielleicht keine Bedeutung hat, ist eine, die den Endnutzer einfach nicht interessiert. Wie du mit solchen Meldungen umgehst, erfährst du in Kapitel 6.

Jetzt, wo du den Grundgedanken kennst, wollen wir uns jeden Schritt genauer ansehen:

Datenstichproben

Wie baust du einen Datensatz auf, um dein Modell zu trainieren, und was ist eine angemessene Stichprobengröße?

Feature-Codierung

Wie kommst du von einer Zeile in einer deiner Tabellen zu einer Reihe von Merkmalen, die dein Modell nutzen kann, um Vorhersagen zu treffen?

Modellentwicklung

Was ist die richtige Modellarchitektur für diesen Algorithmus und wie solltest du das Modell trainieren?

Erklärbarkeit des Modells

Wenn du ein Modell trainiert hast, wie nutzt du es, um ein Datenqualitätsproblem zu erklären?

Datenstichproben

Der Ausgangspunkt für die Entwicklung eines jeden Modells ist die Erstellung eines Trainingsdatensatzes durch Stichproben aus deinem gesamten Datenbestand. Für den Algorithmus, den wir gerade beschrieben haben, brauchst du einen robusten Datensatz mit Zufallsstichproben von "heute" (Label = 1 für die Klasse, die wir vorhersagen wollen) und "nicht heute" (Label = 0). Die "nicht heute"-Daten sollten eine Mischung aus früheren Vergleichszeiträumen sein: gestern (oder das letzte Mal, als du eine Datenaktualisierung erhalten hast) für plötzliche Veränderungen sowie andere Zeiten der Woche oder des Jahres, um die Saisonalität zu berücksichtigen (siehe Abschnitt "Saisonalität").

In Abbildung 4-2 sehen wir einen Beispieldatensatz mit 150.000 bis 250.000 Datenzeilen pro Tag. Eine robuste Stichprobe könnte 10.000 Zeilen von jedem der folgenden Daten enthalten:

  • 2021-01-16: das Datum, das du auf Datenqualitätsprobleme prüfen willst

  • 2021-01-15: gestern, was helfen wird, plötzliche Veränderungen zu erkennen

  • 2021-01-09: vor einer Woche, um die Saisonalität des Wochentags zu kontrollieren

  • 2021-01-02: vor zwei Wochen, für den Fall, dass die letzte Woche Anomalien aufwies

Graph showing sample size compared to the entire size of the dataset
Abbildung 4-2. Das Diagramm zeigt die Stichprobengröße im Vergleich zur Gesamtgröße des Datensatzes.

Stichprobengröße

In der Praxis stellen wir fest, dass dieser Algorithmus mindestens 100 Datensätze pro Tag benötigt, um eine Chance zu haben, sinnvolle Veränderungen in einigermaßen komplexen Daten zu finden. Das wirft jedoch die Frage auf, wie hoch die Anzahl der Datensätze sein sollte, die für den Algorithmus nützlich sind.

Die Abtastrate kann so gewählt werden, dass ein Gleichgewicht zwischen Rechenkosten und Genauigkeit entsteht. Wir haben diesen Algorithmus mit Datensätzen getestet, bei denen täglich bis zu zehn Milliarden Zeilen hinzugefügt werden. In der Praxis und auf der Grundlage strenger Tests haben wir festgestellt, dass 10.000 Datensätze pro Tag (bei einer Zufallsstichprobe) genug Daten liefern, um die meisten Datenqualitätsprobleme zu erfassen, sogar solche, die nur 1-5 % der Datensätze betreffen. Die Qualitätsverbesserung nimmt ab, wenn die Stichprobengröße 100.000 übersteigt.

Große Stichproben (z. B. 1.000.000 Datensätze pro Tag) können verwendet werden, aber der Rechenaufwand hat sich nicht als lohnend erwiesen. Ein Datensatz müsste sehr, sehr stabil sein (wenig Hintergrundchaos) und die Veränderung müsste einen sehr kleinen Prozentsatz der Datensätze betreffen (z. B. 0,1 % der Datensätze), damit sich diese Erhöhung der Stichprobengröße lohnt.

Es kann wie ein Fehler erscheinen, eine feste Stichprobengröße (10.000 Datensätze) zu wählen, anstatt z.B. 10 % der Daten zu beproben. Denn wenn ich 1 Milliarde Datensätze habe, wie können 10.000 dann noch repräsentativ für diese riesige Population sein?

Da die Stichprobe nach dem Zufallsprinzip ausgewählt wird, hängt ihre Genauigkeit nicht von der Gesamtgröße der Daten ab, sondern nur von der absoluten Stichprobengröße, was vielleicht kontraintuitiv ist. Nehmen wir zum Beispiel die Schätzung des Durchschnittseinkommens eines Landes. Nur weil China 1,4 Milliarden Einwohner hat und Luxemburg 600.000 Einwohner, heißt das, dass wir in China mehr Menschen befragen müssten, um das Durchschnittseinkommen zu ermitteln? Nein. In beiden Fällen könnten wir 1.000 Menschen nehmen und bekämen eine sehr gute Schätzung des Durchschnittseinkommens.

Verzerrung und Effizienz

Es ist wichtig, dass die Stichprobe zufällig aus der Tabelle gezogen wird. Wenn die Stichprobe verzerrt ist, kann der Algorithmus diese Verzerrung erkennen und stellt sie als falsch positive Veränderung in den Daten dar, was die Nutzer verwirrt.

Es ist auch wichtig, dass die Stichprobenziehung so effizient wie möglich ist. In der Praxis ist das Heraussuchen zufälliger Datensätze aus dem Data Warehouse für das maschinelle Lernmodell oft der teuerste Vorgang in einem solchen System. Das liegt daran, dass die Tabelle Milliarden oder sogar Billionen von Datensätzen und Hunderte oder Tausende von Spalten enthalten kann. Wenn eine Abfrage naiverweise erfordern würde, dass jeder Datensatz in den Speicher eingelesen oder über ein Netzwerk gesendet werden muss, um eine Stichprobe zu erstellen, wäre das katastrophal für die Leistung und würde hohe Data Warehouse-Kosten verursachen.

Verzerrung und Effizienz können manchmal in einem Spannungsverhältnis zueinander stehen. Eine Möglichkeit, Zufallsstichproben in modernen Data Warehouses effizient zu skalieren, ist zum Beispiel die Verwendung von TABLESAMPLE Operatoren anstelle von random() Aufrufen. Der TABLESAMPLE Operator ist so implementiert, dass das Warehouse während der Ausführung der Abfrage effizient Zufallsdatensätze abfragen kann, ohne die Datensätze in den Speicher einlesen zu müssen.

In BigQuery funktioniert die TABLESAMPLE Operator-Implementierung "durch die zufällige Auswahl eines Prozentsatzes von Datenblöcken aus der Tabelle und das Lesen aller Zeilen in den ausgewählten Blöcken." In der Dokumentation wird weiter erklärt, dass "BigQuery Tabellen oder Tabellenpartitionen in Blöcke aufteilt, wenn sie größer als 1 GB sind". Diese bedeutet, dass in der Praxis die Ergebnisse, die der TABLESAMPLE Operator zurückgibt, in BigQuery oft nicht zufällig sind und stattdessen vollständig in einer einzigen Partition liegen können. Wenn du deine Daten nach einem Identifikator partitioniert hast, den du häufig für Joins verwendest - z. B. eine Kunden-ID -, wirst du bestimmte Untergruppen von Kunden haben, die mit viel höherer Wahrscheinlichkeit in deiner Zufallsstichprobe auftauchen werden als andere. Dies könnte die Ergebnisse deiner ML erheblich verfälschen, da du im Laufe der Zeit immer wieder Veränderungen in der Nutzerpopulation feststellst, die ausschließlich auf die Stichprobenimplementierung zurückzuführen sind und nicht auf eine tatsächliche Abweichung in deinen Daten selbst.

Wie kannst du also effizient Stichproben ziehen und Verzerrungen vermeiden? Hier sind unsere Empfehlungen:

  • Achte darauf, dass du jedes Mal, wenn du den Algorithmus ausführst, nur die Daten einiger weniger Tage verwendest. Diese Tage können als Snapshots gespeichert werden, damit sie nicht erneut abgefragt werden müssen (obwohl es sich lohnen könnte, sie erneut abzufragen, da sich die historischen Daten in der Tabelle geändert haben könnten).

  • Vergewissere dich, dass die Tabelle nach der Datumsspalte partitioniert ist, die du zur Auswahl der Daten verwendest. So kann das Data Warehouse effizient zu den Dateien auf der Festplatte navigieren, die diese Tage repräsentieren, und nur diese Datumsangaben lesen und verarbeiten, ohne auf andere, irrelevante Daten zugreifen zu müssen.

  • Mit dem Operator TABLESAMPLE kannst du effizient eine ungefähre Zufallsstichprobe ziehen, die größer ist als die von dir benötigte (wenn du z. B. 0,3 % brauchst, nimmst du 1 %). Oft liegt die untere Grenze für eine Stichprobe mit diesem Operator bei 1 %, aber die Umsetzung variiert je nach Data Warehouse. Beachte, dass nicht alle Datenbanken oder Data Warehouses TABLESAMPLE auf robuste Weise unterstützen - siehe den vorherigen Absatz über BigQuery.

  • Zähle die Gesamtzahl der Datensätze, die du an den abgefragten Daten hast, um den genauen Prozentsatz der Stichprobe zu ermitteln, die du abfragen musst.

  • Nimm die endgültige Zufallsstichprobe mit einem Code, der wie folgt aussieht: random() <= X für eine X, die dir nach der Operation TABLESAMPLE ungefähr die richtige Anzahl von Zeilen an jedem Datum liefert. Das ist weitaus effizienter als ein Code, der wie order by random() limit 10,000 aussieht, bei dem alle Daten in den Speicher eines Hauptknotens im Lager geladen und nach einer Zufallszahl sortiert werden müssten, bevor eine Begrenzung angewendet wird. Der Vorteil des random() <= X Ansatzes ist, dass er im Warehouse in jedem der Worker-Compute-Nodes verteilt angewendet werden kann. Der kleine Nachteil ist, dass deine Zufallsstichprobe wahrscheinlich nicht genau 10.000 Zeilen umfasst, sondern eher eine Zahl, die ziemlich nah dran ist.

Eine weitere wichtige Überlegung bei der Abfrage von Daten ist es, sicherzustellen, dass der WHERE SQL-Filter effizient implementiert ist. Bei einer Tabelle mit der Datumsspalte created_date, die als Zeichenkette im Format JJJJ-MM-TT angegeben ist, wäre dies zum Beispiel sehr ineffizient:

WHERE cast(created_date as date) = cast('2023-06-01' as date)

Bei diesem Code müsste die Datenbank jede Partition lesen und die Spalte created_date im Speicher umwandeln, um zu entscheiden, ob der Datensatz aufgenommen werden soll.

Versuche es stattdessen:

WHERE created_date = '2023-06-01'

Jetzt kann das Data Warehouse anhand von Metadaten über jede Partition entscheiden, welche von der Abfrage komplett ausgeschlossen werden soll. Das kann bei Tabellen, die mit ungewöhnlichen Datums- oder Zeitpartitionen formatiert sind, eine ziemliche Herausforderung sein. Bei Anomalo mussten wir die Unterstützung für alle in Abbildung 4-3 dargestellten Typen hinzufügen.

Example of types of date/time partitions
Abbildung 4-3. Beispiel für die Arten von Datum/Uhrzeit-Partitionen.

Jeremy scherzt manchmal, dass wir bald die Zeit im Format "Anzahl der Tage seit Kevin Bacons Geburt" unterstützen werden.

Merkmal Kodierung

ML-Modelle werden in der Regel nicht auf Rohdaten trainiert, sondern lernen anhand von numerischen Merkmalen, die die Rohdaten in Signale umwandeln, die das Modell nutzen kann. Die Art und Weise, wie die Rohdaten umgewandelt werden, kann sich erheblich auf die Leistung des Modells auswirken und erfordert in der Regel sowohl ML-Kenntnisse als auch Fachwissen über die Daten und das jeweilige Problem. Dieser Prozess, das sogenannte Feature Engineering, muss in unserem Algorithmus zur Erkennung von Anomalien vollständig automatisiert werden.

Das funktioniert folgendermaßen: Jeder Datensatz in der Stichprobe hat eine Reihe von Spalten, und jede Spalte kann eine Ganzzahl, eine Fließkommazahl, ein String, ein Boolescher Wert, ein Datum oder ein Zeitstempel oder ein komplexer Typ wie JSON oder ein Array sein. Du brauchst einen automatisierten Prozess, der jede Spalte durchläuft (komplexe Typen wie JSON werden bei Bedarf in Unterspalten aufgeteilt - mehr dazu unter "Semistrukturierte Daten" ), Informationen extrahiert, die für dein Modell interessant sein könnten, und diese Informationen in eine Fließkommamatrix von ML-Merkmalen kodiert.

Encoding data as features. Note that the response variable (a.k.a. label) corresponds to the date: 0 for yesterday and 1 for today.
Abbildung 4-4. Kodierung von Daten als Merkmale. Beachte, dass die Antwortvariable (auch bekannt als Label) dem Datum entspricht: 0 für gestern und 1 für heute. Eine Version dieses Bildes in voller Größe findest du unter https://oreil.ly/adqm_4_4.

Du solltest eine Bibliothek mit in Frage kommenden Encodertypen entwickeln, die auf den Merkmalen basieren, von denen du glaubst, dass sie Aufschluss darüber geben können, ob sich die Daten auf sinnvolle Weise verändert haben (siehe Abbildung 4-4). Hier sind einige von uns empfohlene Encoder:

Numeric

Konvertiert boolesche, ganzzahlige und fließende Werte in Fließkommazahlen

Frequency

Wie oft jeder Wert in der Datenstichprobe vorkommt

IsNull

Ein binärer Indikator dafür, ob die Spalte NULL ist

TimeDelta

Sekunden zwischen einer Zeit und dem Zeitpunkt, an dem der Datensatz erstellt wurde

SecondOfDay

Die Tageszeit, zu der der Datensatz erstellt wurde

OneHot

Ein One-Hot-Encoder, mit dem du Merkmalswerte (wie Kategorien oder häufige ganzzahlige Werte) auf eine binäre Ja- oder Nein-Indikatorvariable für jeden einzelnen Wert in der Spalte abbilden kannst

Datenwissenschaftler fragen sich vielleicht nach der Anwendbarkeit gängiger Kodierer wie Termfrequenz-inverse Dokumentenhäufigkeit (TF-IDF), Mittelwertkodierung oder Laplace-Glättung. Viele Standardkodierer sind für baumbasierte Modelle nicht sehr relevant (Log-Transformation, Mittelwertkodierung, Hauptkomponentenanalyse [PCA]). Andere erfordern viel Fachwissen über die spezifischen Daten, um sie gut zu nutzen (Laplace-Glättung), und wieder andere sind zwar nützlich, aber sehr schwer zu interpretieren (TF-IDF, Wort-/Vektoreinbettung).

Du musst darauf achten, wie komplex du deine Kodierungen gestaltest, denn schließlich musst du diese Kodierungen verwenden, um dem Nutzer das Problem der Datenqualität zu erklären. Wir haben zum Beispiel einen "Lücken"-Codierer für Zeit-, Ganzzahl- und numerische Felder getestet, der für jede Beobachtung die Lücke zwischen ihr und dem nächstgrößeren Wert in dieser Spalte berechnet. In der Praxis ließen sich damit einige Probleme mit der Datenqualität erkennen, aber auch viele andere Veränderungen in den Daten, die schwer zu verstehen und/oder für unsere Zwecke irrelevant sind, wie z. B. Veränderungen in der Struktur der Datenerfassung oder unzusammenhängende Veränderungen im Volumen (und damit in der Dichte) der Beobachtungen.

Modellentwicklung

Um die Anforderungen von an die Skalierbarkeit zu erfüllen und in der Praxis zu funktionieren, brauchst du eine Modellarchitektur, die schnell bei der Inferenz und beim Training ist, auf relativ kleinen Stichproben trainiert werden kann und sich auf jede Art von Tabellendaten verallgemeinern lässt (wenn die Merkmale richtig kodiert sind). Gradient-Boosted-Entscheidungsbäume eignen sich gut für diesen Anwendungsfall, und für die Modellentwicklung sind Bibliotheken wie XGBoost leicht verfügbar.

Gradient-Boosted-Entscheidungsbäume arbeiten iterativ, indem sie eine Abfolge von Entscheidungsbäumen auf dem Datensatz aufbauen, wobei jeder Baum (oder "Schritt") darauf ausgelegt ist, die Fehler aller Bäume vor ihm zu korrigieren. Letztendlich berücksichtigt die Vorhersage des Modells die Ergebnisse aller Bäume, die in den einzelnen Schritten trainiert wurden (dies wird als Ensemble-Modell bezeichnet). Siehe Abbildung 4-5.

A gradient-boosted decision tree (adapted from Haowen Deng et al., “Ensemble Learning for the Prediction of Neonatal Jaundice with Genetic Features,” BMC Medical Informatics and Decision Making, 2011)
Abbildung 4-5. Ein gradient-boosted Entscheidungsbaum (nach Haowen Deng et al., "Ensemble Learning for the Early Prediction of Neonatal Jaundice with Genetic Features", BMC Medical Informatics and Decision Making 21, no. 338 [2021]).

Hilfreich ist, dass gradient-boosted Entscheidungsbäume nur eine sehr geringe Anzahl von Parametern haben, die für die Abstimmung wirklich wichtig sind (hauptsächlich die Lernrate und die Komplexität jedes Baums, obwohl es noch andere gibt) und sehr schnell auf Datensätzen mit Tausenden oder sogar Millionen von Datensätzen trainiert werden können.

Einige alternative Ansätze, wie lineare Modelle, sind zu einfach, um die komplexen Muster in den meisten strukturierten Datensätzen zu lernen. Andere Ansätze, wie z. B. neuronale Netze, sind für solche Probleme oft zu komplex und benötigen extrem große Mengen heterogener Daten, um sehr leistungsfähig zu werden (wie bei Bild- und Sprachmodellen).

Der Nachteil von Gradient-Boosted-Entscheidungsbäumen ist, wie bei allen strukturierten ML-Techniken, dass sie Feature-Engineering erfordern: Menschliche Experten müssen dem Modell sagen, welche Aspekte der Daten es bei seinen Vorhersagen berücksichtigen soll, und das kann viel Zeit und Energie kosten.

Ausbildung und Bewertung

Theoretisch könnten gradient-boosted Entscheidungsbäume endlos weiter iterieren, daher ist es wichtig, die Anzahl der Schritte auf eine bestimmte Anzahl zu begrenzen. Daher ist es wichtig, die Anzahl der Schritte zu begrenzen. Um dies zu tun, solltest du die Leistung des Modells nach jedem Schritt bewerten. Wähle einen zufälligen Teil deiner Daten als Überbrückungsmenge für die Auswertung (und nicht für das Training) und teste das Modell nach jeder Iteration. Die Leistung deines Modells gibt Aufschluss darüber, ob es bei den heutigen Daten eine Anomalie gibt.

In Abbildung 4-6 sind drei Muster der Modellleistung dargestellt, die wir in der Praxis häufig sehen. In diesen Diagrammen stellt die x-Achse die Anzahl der zum Modell hinzugefügten Bäume dar (die Anzahl der Iterationen), während die y-Achse ein Maß für die Genauigkeit des Modells darstellt (den Logarithmus der Verlustfunktion). Die y-Achse gibt an, wie groß der "Fehler" in den Vorhersagen des Modells ist, d. h. ein niedrigerer Wert bedeutet eine höhere Genauigkeit.

Das erste Szenario, "Keine Anomalie", bedeutet, dass bei den Trainingsdaten kaum Fortschritte erzielt werden und die Leistung bei den Testdaten sehr schnell schlechter wird. Das bedeutet, dass es in den neuen Daten wahrscheinlich keine Anomalie gibt.

Das zweite Szenario, "unvollständig", tritt ein, wenn das Modell nicht genug Zeit hat, um zu konvergieren. Du erreichst eine maximale Anzahl von Bäumen (die so eingestellt ist, dass das Modell nicht unendlich lange läuft) und stellst trotzdem fest, dass der Trainingsfehler und der Testfehler abnehmen. Dann musst du entweder mehr Bäume hinzufügen oder, was vielleicht vorsichtiger ist, die Lernrate erhöhen, was den Gradient-Boosting-Algorithmus veranlasst, größere "Schritte" in Richtung jedes Baumes zu machen, den er auswertet.

Das dritte Szenario, "Optimal", tritt ein, wenn das Modell beim Training und beim Test gute Fortschritte macht, bis zu einem Punkt, an dem der Testverlust zu steigen beginnt. Das bedeutet, dass du an dem Punkt aufhören kannst, an dem der Testverlust sein Minimum erreicht hat. An diesem Punkt hat das Modell so viel über die Unterschiede zwischen den beiden Datensätzen gelernt, wie es mit den anderen Parametern des Lernalgorithmus möglich ist.

The three most common scenarios encountered when plotting the model’s performance on training and test data as the number of trees increases. Performance is measured using a log loss error function (a lower value on the y-axis indicates better performance).
Abbildung 4-6. Die drei häufigsten Szenarien, die bei der Darstellung der Leistung des Modells bei Trainings- und Testdaten mit zunehmender Anzahl von Bäumen auftreten. Die Leistung wird mit einer logarithmischen Fehlerfunktion gemessen (ein niedrigerer Wert auf der y-Achse bedeutet eine bessere Leistung).

In der Praxis musst du einen Mittelweg finden zwischen der Optimierung deines Modells für einen einzelnen Datensatz und der Entwicklung eines Modells, das sich auf viele Datensätze über verschiedene Zeiträume hinweg verallgemeinern lässt, um konsistent interpretierbare Modellstatistiken und Erklärungsergebnisse zu liefern.

Berechnungseffizienz

Viele Organisationen haben wichtige Tabellen, die Milliarden von Datensätzen enthalten können. Beispiele hierfür sind:

  • Transaktionsdaten aus der Finanzdienstleistungsbranche

  • Rohe Ereignisdaten von stark frequentierten Anwendungen oder Websites

  • Daten zu digitalen Werbeeinblendungen und Ereignissen

  • Physikalische Sensordaten

  • Nachrichteninformationen von sozialen Plattformen

Bei Daten dieser Größenordnung ist es leicht, eine Überwachungsstrategie zu entwickeln, die kostspielig ist oder selbst bei modernen Data Warehouses einfach fehlschlägt.

Da wir die Anzahl der Datensätze, die wir pro Tag abfragen, begrenzt haben, skalieren die meisten Berechnungen und der Speicherbedarf des Modells linear mit der Anzahl der hinzugefügten Spalten. Die Suche nach dem besten Split und die Erweiterung eines Entscheidungsbaums an jedem Knotenpunkt steigt beispielsweise linear mit der Anzahl der Spalten, die durchsucht werden müssen. Obwohl typische Tabellen 10-50 Spalten haben, ist es üblich, dass Tabellen 200 Spalten haben, und manche Tabellen haben sogar Tausende. Außerdem können Tabellen JSON-Daten enthalten, die du automatisch in neue synthetische Spalten erweitern musst, was in manchen Situationen zu Tabellen mit 10.000 Spalten führen kann.

Die folgenden Optimierungen können deinen Algorithmus rechnerisch effizienter machen:

  • Sicherstellen, dass du jeweils nur einen Tag Daten abfragst und die Ergebnisse so oft wie möglich in Momentaufnahmen festhältst, um eine Historie aufzubauen. Das hat allerdings seinen Preis, denn die Algorithmen können am ersten Tag mit weniger Daten arbeiten und sind in einem "Kaltstart"-Szenario nicht so effektiv.

  • Stichprobenartige Entnahme von Datensätzen aus der Tabelle mit Hilfe des Data Warehouse (unter Verwendung der oben unter "Verzerrung und Effizienz" beschriebenen effizienten Techniken ) und Berechnung komplexerer Profiling- oder ML-Ergebnisse auf der Grundlage der Stichproben.

  • Wenn du Gradient-Boosting-Entscheidungsbäume verwendest, solltest du die Tiefe und die Gesamtzahl der Bäume begrenzen, da wir in der Regel nicht nach sehr komplexen Wechselwirkungen suchen, und frühzeitig aufhören, wenn dein Testfehler während des Trainings deutlich zunimmt.

  • Optimiere den Lernprozess selbst, was je nach Computerplattform und Lernalgorithmus Schritte wie die Verwendung von Sparse Encodings, die Verteilung des Lernens über Multiprocessing oder die Nutzung von GPUs beinhalten kann.

Modell Erklärbarkeit

Wenn dein Modell in der Testmenge gut abschneidet, bedeutet das, dass du ein mögliches Problem mit der Datenqualität gefunden hast. Im nächsten Schritt musst du erklären, was das Modell herausgefunden hat.

Die Erklärbarkeit ist aus mehreren Gründen wichtig. Erstens sagt sie dir, wie anormal die Daten von heute sind. So kannst du viele Einstellungen vornehmen, um Alarmmüdigkeit zu vermeiden (mehr dazu in Kapitel 5 und 6). Bei Problemen, bei denen du eine Warnung auslöst, hilft die Kenntnis des Schweregrads den Endnutzern, ihre Reaktion zu priorisieren.

Zweitens sagt dir die Erklärbarkeit, wo in den Daten die Anomalie zu finden ist. So kannst du Ermittler auf die richtigen Datensegmente hinweisen und alle möglichen interessanten Hilfsmittel für die Ursachenanalyse erstellen, z. B. Stichproben von schlechten Daten (mehr dazu in Kapitel 6).

Wie funktioniert also die Erklärbarkeit von Modellen? Die Idee ist, einen Wert abzuleiten, der angibt, wie viel jede einzelne Zelle {Zeile, Spalte} im Datensatz zur Vorhersage des Modells beigetragen hat. Es gibt zwar verschiedene Ansätze, aber wir verwenden SHAP, das im Wesentlichen eine lokale lineare Schätzung dessen ist, was der Algorithmus für jede Zelle im Datensatz tut.

Um zu sehen, wie das in der Praxis funktioniert, nehmen wir an, dass wir versuchen, Datenqualitätsprobleme in einer Tabelle mit Kreditkartentransaktionsdaten zu erkennen. Wir haben 10.000 Datensätze von gestern und heute ausgewählt, unsere Merkmale kodiert und ein Modell erstellt, das vorhersagt, an welchem Tag jeder Datensatz eingegangen ist. Dann wollen wir die folgenden vier Datensätze durch den SHAP-Erklärungsprozess verfolgen:

Betrag Typ FICO-Score Marke Typ Kreditlimit Quelle
$18 Swipe 684 Entdecke Debit $12,564 Heute
$59 Chip 578 Mastercard Kredit $7,600 Heute
-$445 Chip 689 Visa Kredit $6,700 Gestern
$137 Chip 734 Mastercard Kredit $7,100 Gestern

In diesem Fall haben wir zwei Datensätze von gestern und zwei Datensätze von heute. (Erinnere dich daran, dass die Quellspalte nicht verwendet wird, um Vorhersagen darüber zu treffen, an welchem Tag die Daten angekommen sind; vielmehr ist es die Antwort, für die wir das Modell trainieren).

Dann nehmen wir an, dass wir unser Modell nehmen und für jede Zeile vorhersagen, an welchem Tag sie wahrscheinlich eingetroffen sein wird:

Betrag Typ FICO-Score Marke Typ Kreditlimit Quelle Vorhersage Pr( Heute )
$18 Swipe 684 Entdecke Debit $12,564 Heute 51%
$59 Chip 578 Mastercard Kredit $7,600 Heute 78%
-$445 Chip 689 Visa Kredit $6,700 Gestern 45%
$137 Chip 734 Mastercard Kredit $7,100 Gestern 52%

In diesem Fall stellt sich heraus, dass unser Modell eine 78%ige Chance sieht, dass der zweite Datensatz von heute stammt, während die anderen drei Datensätze innerhalb von ±5% der durchschnittlichen Vorhersage von 50% liegen, was darauf hindeutet, dass das Modell keine starke Voreingenommenheit dafür hat, von welchem Tag die Daten stammen.

Anstatt direkt mit der vorhergesagten Wahrscheinlichkeit zu arbeiten (die schwer als lineare Beziehung auszudrücken ist, da Wahrscheinlichkeiten naturgemäß zwischen 0% und 100% begrenzt sind), wandeln wir die Wahrscheinlichkeiten in ihre logarithmischen Quoten um, indem wir die Formel log odds = ln [ probability / (1 - probability) ] verwenden:

Betrag Typ FICO-Score Marke Typ Kreditlimit Quelle Vorhersage Pr( Heute ) Log Quoten
$18 Swipe 684 Entdecke Debit $12,564 Heute 51% 0.02
$59 Chip 578 Mastercard Kredit $7,600 Heute 78% 0.55
-$445 Chip 689 Visa Kredit $6,700 Gestern 45% -0.09
$137 Chip 734 Mastercard Kredit $7,100 Gestern 52% 0.03

Dann können wir den SHAP-Algorithmus ausführen, der diese Log Odds-Statistiken in eine lineare Kombination aus den Beiträgen der einzelnen Spalten zerlegt, wie sie im ML-Modell verwendet werden (in Wirklichkeit müssten wir die SHAP-Werte auf Merkmalsebene ermitteln und diese dann aggregieren, aber du verstehst schon):

Betrag Typ FICO-Score Marke Typ Kreditlimit Vorhersage Pr( Heute ) Vorhersage Pr( Heute ) Log Quoten
0.01 0.02 0.02 -0.01 0.00 -0.01 Heute 51% 0.02
-0.03 0.01 0.41 0.19 -0.01 -0.03 Heute 78% 0.55
0.02 -0.03 -0.05 0.02 -0.03 -0.02 Gestern 45% -0.09
0.01 -0.02 -0.01 0.01 0.02 0.02 Gestern 52% 0.03

In diesem Fall stellen wir fest, dass die Werte der Spalten FICO SCORE und BRAND wesentlich zur Vorhersage des Modells beitragen, dass der zweite Datensatz von heute stammt. Anhand der obigen Datenwerte können wir erkennen, dass dies entspricht:

  • FICO SCORE = 578

  • BRAND = 'Mastercard'

Das deutet darauf hin, dass es bei der Verteilung der niedrigen Kreditwürdigkeitswerte für Mastercard-Transaktionen etwas Ungewöhnliches geben könnte (obwohl wir hier nur einige wenige Datensätze untersuchen - in der Praxis würden wir die Verteilung der SHAP-Werte über alle 10.000 Datensätze pro Tag zusammenfassen).

Nachdem die SHAP-Werte gemäß den in Kapitel 5 beschriebenen Techniken normalisiert und entsprechend angepasst wurden, ist das Endergebnis der sogenannte "Anomalie-Score". Wichtig ist, dass dieser Wert aggregiert und/oder gesliced werden kann, um viele verschiedene Granularitätsebenen zu erhalten.

Auf der untersten Ebene kannst du dir den Anomalie-Score für jede einzelne Zelle {Zeile, Spalte} in den Stichprobendaten ansehen. Von hier aus kannst du die Anomaliewerte für eine Zeile aggregieren, um die anomalsten Einträge zu finden, oder nach Zeilengruppen, um anomale Segmente zu finden. Du kannst den Durchschnittswert der Anomalien pro Spalte ermitteln, um die anomalsten Spalten zu finden. Du kannst auch die Anomaliebewertung für die gesamte Tabelle berechnen. Du kannst die Anomaliewerte auch clustern, um Korrelationen zwischen den Spalten zu finden (mehr dazu in Kapitel 5).

Die Kenntnis des Anomalie-Scores ist nicht nur für Daten wichtig, bei denen es eine signifikante Veränderung gegeben hat. Indem du den Wert für jeden Datensatz in der Tabelle berechnest, kannst du Visualisierungen erstellen, die die Anomalie in einen Kontext setzen, wie in Abbildung 4-7.

In this sample merchants dataset, the data quality monitoring platform has detected an issue where the value fastfood has decreased significantly in the column merchantcategorycode. The anomaly score is compared to the anomaly score for other values in this table. You can see that there was simultaneously a significant increase in the value food. These two changes may be related, as suddenly fastfood records were misclassified as simply food.
Abbildung 4-7. In diesem Beispieldatensatz von Kaufleuten hat die Plattform zur Überwachung der Datenqualität ein Problem entdeckt, bei dem der Wert fastfood in der Spalte merchantcategorycode deutlich gesunken ist. Der Anomalie-Score wird mit dem Anomalie-Score für andere Werte in dieser Tabelle verglichen. Du kannst sehen, dass es gleichzeitig einen deutlichen Anstieg des Wertes food gab. Diese beiden Änderungen könnten zusammenhängen, da plötzlich fastfood Datensätze fälschlicherweise als food klassifiziert wurden. Eine Vollversion dieses Bildes findest du unter https://oreil.ly/adqm_4_7.

Wie du in Abbildung 4-7 sehen kannst, kannst du den Anomaliewerten Kategorien zuweisen, die für den Menschen lesbar sind und die Interpretation erleichtern. Aufgrund unserer Erfahrung mit einer Vielzahl von Datensätzen haben wir die Anomaliewerte in sechs verschiedene Kategorien eingeteilt, von minimal bis extrem. Diese Kategorien basieren auf dem Logarithmus der Gesamtauffälligkeitsbewertung - alle zwei Bereiche entsprechen einer Erhöhung der Bewertung um eine Größenordnung:

Minimal

Es gibt wenig bis keine signifikanten Veränderungen in den Daten.

Schwach

Ein kleiner Prozentsatz der Daten ist von einer Veränderung betroffen, die zu erkennen eine Erklärung und sorgfältige Untersuchung erfordert.

Mäßig

Ein kleiner Prozentsatz der Daten ist von einer offensichtlichen Veränderung betroffen, oder ein mäßiger Prozentsatz ist von einer Veränderung betroffen, die eine einfache Erklärung erfordert.

Stark

Ein signifikanter Prozentsatz der Daten ist von einer offensichtlichen Veränderung betroffen, oder ein Großteil der Daten ist von einer Veränderung betroffen, die leicht zu erklären ist (auch wenn sie auf den ersten Blick nicht offensichtlich ist).

Schwere

Ein Großteil der Daten unterliegt einer Veränderung, die offensichtlich ist.

Extrem

Es gibt eine Änderung, die sich offensichtlich auf fast die Gesamtheit der Daten von heute auswirkt.

In Abbildung 4-7siehst du vielleicht einen Schwellenwert - esist wichtig, dass du den Anomalie-Score für jede Tabelle verwendest, um einen benutzerdefinierten Schwellenwert für die Auslösung eines Alarms zu lernen, da sich die Daten in einigen Tabellen häufiger ändern als in anderen. Wir werden dies in Kapitel 5 besprechen.

Zusammensetzen mit Pseudocode

Der folgende Python-Pseudocode ist ein Beispiel dafür, wie du den in diesem Kapitel beschriebenen Ansatz anwenden kannst, um Anomalien zwischen zwei Datentagen zu finden und sie nach Spalten zusammenzufassen. Nimm diesen Code jedoch nicht zu wörtlich; er soll lediglich die Konzepte veranschaulichen und zeigen, wie sie auf hohem Niveau zusammenpassen. Beachte vor allem, dass komplexere Aspekte wie Saisonalität, mehrfache Rückblicke und korrelierte Merkmale nicht berücksichtigt werden und das Sampling, das Feature-Engineering und die Berechnung der Anomalie-Scores nicht im Detail implementiert sind.

# General imports
import pandas as pd
import datetime as dt
import xgboost as xgb
from sklearn.model_selection import train_test_split
from shap import TreeExplainer

# Import hypothetical sub-modules that perform more detailed tasks
from data_access import query_random_sample
from feature_engineering import determine_features, encode_feature
from explainability import compute_column_scores

def detect_anomalies(
        table: str,
        time_column: str,
        current_date: dt.date,
        prior_date: dt.date,
        sample_size: int
    ) -> dict[str, float]:

Hier definieren wir eine Methode in Pseudocode, die Anomalien in Daten aufdeckt, indem wir Stichproben aus zwei verschiedenen Zeitpunkten vergleichen, ein Modell trainieren und Anomalie-Scores errechnen.

Sie akzeptiert die folgenden Parameter:

table

der Name der abzufragenden Tabelle

time_column

der Name der Zeitspalte, die zum Filtern der Daten verwendet wird

current_date

das aktuelle Datum, für das Daten abgerufen werden sollen

prior_date

das frühere Datum, für das Daten entnommen werden sollen

sample_size

die Anzahl der Zeilen, die für jedes Datum zufällig ausgewählt werden

Sie gibt ein Wörterbuch zurück, in dem jeder Schlüssel ein Spaltenname und jeder Wert die Anomaliebewertung der Spalte ist.

Der nächste Teil des Pseudocodes implementiert den Hauptteil der Methode und führt uns vom Schritt des Datensamplings bis hin zur Erklärung der Vorhersagen des Modells:

    # Obtain random samples of data for the specified dates
    data_current = query_random_sample(
        table, time_column, current_date, sample_size)
    data_prior = query_random_sample(
        table, time_column, prior_date, sample_size)

    # Create a binary response variable indicating the date
    y = [1] * len(data_current) + [0] * len(data_prior)

    # Concatenate the data, ensuring the order of concatenation
    data_all = pd.concat([data_current, data_prior], ignore_index=True)

    # Determine the features to build based on the data columns
    feature_list = {
        column: determine_features(data_all, column) 
        for column in data_all.columns
    }

    # Encode the features, here assuming that encode_feature returns a DataFrame
    encoded_features = [
        encode_feature(data_all, column, feature) 
        for column, feature in feature_list
    ]

    # Combine the encoded features into a single DataFrame
    X = pd.concat(encoded_features, axis=1)

    # Split data into training and evaluation sets
    X_train, X_eval, y_train, y_eval = train_test_split(
        X, y, test_size=0.2, random_state=42
    )

    # Train a machine learning model using the features and response variable
    model = xgb.XGBClassifier()
    model.fit(
        X_train, 
        y_train, 
        early_stopping_rounds=10, 
        eval_set=[(X_eval, y_eval)], 
        verbose=False,
    )

    # Obtain SHAP values to explain the model's predictions
    explainer = TreeExplainer(model)
    shap_values = explainer.shap_values(X)

    # Compute anomaly scores for each column based on the SHAP values
    column_scores = compute_column_scores(shap_values, feature_list)
    return column_scores

Andere Anwendungen

Wir haben uns darauf konzentriert, wie unüberwachte ML dir helfen kann, plötzliche strukturelle Veränderungen in deinen Daten laufend zu erkennen. Der in diesem Kapitel beschriebene ML-Ansatz hat jedoch noch zwei weitere Anwendungsfälle, die es wert sind, erwähnt zu werden.

Die erste besteht darin, alte Datenqualitätsprobleme zu finden, die sich als Schocks und Narben in der Geschichte deiner Daten zeigen. Dazu kannst du den in diesem Kapitel beschriebenen Algorithmus auf eine Reihe von historischen Daten anwenden und die gefundenen Anomalien untersuchen. In Kapitel 5 werden wir beschreiben, wie wir diesen Prozess, den wir Backtesting nennen, nutzen, um zu messen, wie effektiv unsere Modelle sind.

Aber Vorsicht, denn dieser Ansatz kann einige Komplikationen mit sich bringen. Erstens kann es sein, dass du auf Probleme stößt, die sehr schwer zu erklären sind. Oft gibt es Änderungen, an die sich niemand in der Organisation erinnert, und die Überprüfung, ob sie relevant sind oder nicht, würde teure und langwierige Detektivarbeit erfordern. Die zweite Komplikation besteht darin, dass du vielleicht erwartest, Probleme zu finden, die einfach nicht da sind. Das passiert oft, wenn bekannte Datenqualitätsprobleme behoben werden und ein Team die Daten wieder auffüllt, um die Narbe zu reparieren. Sobald das passiert, solltest du das Problem in der Historie deiner Daten nicht mehr erkennen können.

Der zweite Anwendungsfall ist bedeutsamer und wir werden ihn hier nur kurz ansprechen. Anstatt unüberwachte ML zu verwenden, um Daten in derselben Tabelle im Zeitverlauf zu vergleichen, kannst du stattdessen zwei Stichproben von Daten aus derselben Tabelle (oder aus verschiedenen Tabellen mit demselben Spaltenschema) vergleichen, um aussagekräftige Unterschiede zwischen ihnen zu finden.

In diesem Fall wird der unüberwachte ML-Algorithmus alle signifikanten Verteilungsunterschiede oder Beziehungsunterschiede zwischen den beiden Datensätzen erkennen und erklären helfen. Da dieser Ansatz auf Stichproben basiert, kann er auch auf große Tabellen angewandt werden und sogar auf Tabellen, die sich in verschiedenen Quelllagern oder Datenbanken befinden!

Dies ermöglicht die folgenden Arten von Anwendungen:

  • Vergleich von Rohdaten aus einer Quelldatenbank mit bereinigten und transformierten Daten im Ziel-Warehouse

  • Vergleich der Daten aus der aktuellen Version deiner ETL-Pipeline mit den Daten, die von einer neuen vorgeschlagenen Version erzeugt werden

  • Vergleich einer aktuellen Datenstichprobe mit einer Stichprobe aus der fernen Vergangenheit

  • Vergleich von Daten aus verschiedenen Geschäftsbereichen, Regionen, Produktkategorien oder Marketingkampagnen

Abbildung 4-8 zeigt, wie eine Überwachungsplattform diese Funktion als benutzerdefinierte Prüfung bereitstellen kann, die von den Nutzern konfiguriert und bei Bedarf ausgeführt werden kann, um Datensätze von Interesse zu vergleichen und gegenüberzustellen.

Fazit

Egal, ob du ein erfahrener Datenwissenschaftler oder ein Neuling auf dem Gebiet des maschinellen Lernens bist, wir hoffen, dass dieses Kapitel eine nützliche Einführung in die Erstellung eines Modells war, das plötzliche Veränderungen in der Datenverteilung von einem Tag auf den anderen erkennt. Wir haben uns mit dem Gesamtkonzept befasst, bei dem es darum geht, einen Klassifikator zu erstellen, der vorhersagt, ob eine bestimmte Zeile in der Tabelle zu den Daten von heute gehört. Wenn du das kannst, hat sich an den heutigen Daten eindeutig etwas geändert. Mithilfe der SHAP-Werte kannst du einzelnen Zeilen in der Tabelle eine Punktzahl geben, die angibt, inwieweit sie dem Modell bei seiner Entscheidung geholfen haben. Für die Überwachung der Datenqualität können diese Werte zu Indikatoren dafür werden, wie ungewöhnlich diese Daten sind und auf welche Weise. Dieser Ansatz kann sogar erweitert werden, um historische Veränderungen in deinen Daten zu erklären oder zwei SQL-Abfrageergebnisse zu vergleichen.

Using unsupervised ML, a data quality monitoring platform can expose a check that allows users to compare two datasets.
Abbildung 4-8. Mithilfe von unüberwachtem ML kann eine Plattform zur Überwachung der Datenqualität eine Prüfung anbieten, mit der Nutzer zwei Datensätze vergleichen können.

Die Schritte, die wir gerade beschrieben haben, mögen in der Praxis einfach klingen, aber alles ändert sich, wenn du mit echten Daten arbeitest. Echte Daten weisen saisonale Trends auf, enthalten Korrelationen, die du nicht als separate Themen behandeln willst, und werden oft ohne aktualisiert - um nur einige Hürden zu nennen. Auf diese Herausforderungen und wie du sie überwinden kannst, gehen wir in Kapitel 5 ein.

Get Die Überwachung der Datenqualität automatisieren now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.