Data Science, Machine Learning und KI
Kontakt

Du willst Python lernen? Oder bist du ein R-Profi und dir entfallen bei der Arbeit mit Python regelmäßig die wichtigen Funktionen und Befehle? Oder vielleicht brauchst du von Zeit zu Zeit eine kleine Gedächtnisstütze beim Programmieren? Genau dafür wurden Cheatsheets erfunden!

Cheatsheets helfen dir in all diesen Situationen weiter. Unser erstes Cheatsheet mit den Grundlagen von Python ist der Start einer neuen Blog-Serie, in der weitere Cheatsheets in unserem einzigartigen STATWORX Stil folgen werden.

Du kannst also neugierig sein auf unsere Serie von neuen Python-Cheatsheets, die sowohl Grundlagen als auch Pakete und Arbeitsfelder, die für Data Science relevant sind, behandeln werden.

Unsere Cheatsheets stehen euch zum kostenfreien Download frei zur Verfügung, ohne Anmeldung oder sonstige Paywall.

 

Warum haben wir neue Cheatsheets erstellt?

Als erfahrene R User sucht man schier endlos nach entsprechend modernen Python Cheatsheets, ähnlich denen, die du von R Studio kennst.

Klar, es gibt eine Vielzahl von Cheatsheets für jeden Themenbereich, die sich aber in Design und Inhalt stark unterscheiden. Sobald man mehrere Cheatsheets in unterschiedlichen Designs verwendet, muss man sich ständig neu orientieren und verliert so insgesamt viel Zeit. Für uns als Data Scientists ist es wichtig, einheitliche Cheatsheets zu haben, anhand derer wir schnell die gewünschte Funktion oder den Befehl finden können.

Diesem nervigen Zusammensuchen von Informationen wollen wir entgegenwirken. Daher möchten wir auf unserem Blog zukünftig regelmäßig neue Cheatsheets in einer Designsprache veröffentlichen – und euch alle an dieser Arbeitserleichterung teilhaben lassen.

 

Was enthält das erste Cheatsheet?

Unser erstes Cheatsheet in dieser Reihe richtet sich in erster Linie an Python-Neulinge, an R-Nutzer, die Python seltener verwenden, oder an Leute, die gerade erst anfangen, mit Python zu arbeiten.

Es erleichtert den Einstieg und Überblick in Python. Die grundlegende Syntax, die Datentypen und der Umgang mit diesen werden vorgestellt und grundlegende Kontrollstrukturen eingeführt. So kannst du schnell auf die Inhalte zugreifen, die du z.B. in unserer STATWORX Academy gelernt hast oder dir die Grundlagen für dein nächstes Programmierprojekt ins Gedächtnis rufen.

Was behandelt das STATWORX Cheatsheet Episode 2?

Das nächste Cheatsheet behandelt den ersten Schritt eines Data Scientists in einem neuen Projekt: Data Wrangling. Außerdem erwartet dich ein Cheatsheet für pandas über das Laden, Auswählen, Manipulieren, Aggregieren und Zusammenführen von Daten. Happy Coding!

Niklas Junker

Management Summary

Im Kundenlebenszyklus gilt es, den Kunden zum richtigen Zeitpunkt mit dem richtigen Angebot zu kontaktieren. Dabei sollen aktive Kunden zu einem weiteren Einkauf motiviert oder inaktive Kunden reaktiviert werden. Der Retailer kann seinen Kunden hierzu vielfältige Angebot machen, bspw. durch individuelle Produktempfehlungen, kundenspezifische Rabattaktionen oder ereignisbasierte Marketingaktionen. Häufig ist das Ziel dabei, möglichst die Kunden auszuwählen, mit denen Umsatz bei möglichst geringen Kosten generiert werden kann.

Zur Lösung dieser Herausforderung haben wir bei STATWORX hierzu für einen Kunden aus dem Einzelhandel einen ganzheitlichen Ansatz entwickelt. Auf Basis von Kundenstamm- und Transaktionsdaten haben wir verschiedene state-of-the-art Methoden des Machine Learnings und der künstlichen Intelligenz genutzt, um Kundengruppen individuell und automatisiert auf verschiedenen Kanälen ansprechen zu können. Unser Kunde hatte zwei zentrale Herausforderungen im Direktmarketing identifiziert, die durch die bisher verwendeten Methoden nicht zufriedenstellend gelöst werden konnten:

  1. Customer Churn & Retention: Wann und wie sollten inaktive Kunden gezielt angesprochen werden, um eine Abwanderung möglichst effizient zu verhindern? (Outbound Marketing)
  2. Next Basket Prediction: Welche Produkte sollten aktiven Kunden empfohlen werden, die sie zu einem Folgekauf anregen können? (Inbound Marketing)

Für die Kundenreaktivierung wird zunächst die Kaufwahrscheinlichkeit aller Kunden für einen definierten Zeitraum in der Zukunft ermittelt. Diese Prognose dient dazu, Kunden, die eine sehr hohe Wahrscheinlichkeit für einen Kauf haben, für das weitere Prozedere auszuschließen. Denn diese Kunden müssen ohnehin nicht im Rahmen einer Kampagne reaktiviert werden. Genauso können Kunden ausgeschlossen werden, die eine sehr niedrige Kaufwahrscheinlichkeit aufweisen, da eine Reaktivierung dieser Kunden grundsätzlich wenig erfolgversprechend ist.

Im Anschluss an diesen ersten Schritt wird ein zweites Machine Learning Modell angewendet, das für jeden Kunden individuell aus einer im Vorhinein definierten Auswahl an Rabattgutscheinen den jeweils optimalen Gutschein selektiert.

Die Newsletter, inklusive der entsprechenden Rabattgutscheine, werden automatisiert an die Kunden versendet. Daraufhin wird die Aktivität der Kunden im Aktionszeitraum beobachtet und als Trainingsmenge in das zweite Modell eingespeist sowie die Kampagne anhand der Aktivierungs- und Reaktionsquoten evaluiert.

Zur Empfehlung weiterer Produkte an aktive Kunden wird ein state-of-the-art Modell aus der aktuellen Forschung genutzt. Das Modell nutzt rekurrente neuronale Netze (RNN), um die gesamte Kaufhistorie des Kunden berücksichtigen zu können. Es erlernt nicht nur die dynamische Repräsentation der Kunden, sondern erfasst auch globale sequentielle Merkmale über alle Warenkörbe hinweg. Basierend auf diesem Modell können Newsletter mit kundenindividuellen Produktempfehlungen versendet werden.

Mithilfe dieser beiden Ansätze können die Retail-Kunden in allen Phasen des Kundenlebenszyklus‘ optimal angesprochen, der manuelle Aufwand bei der Kundenauswahl und Versendung des Contents signifikant reduziert und der zur Aktion zugeordnete Umsatz gesteigert werden.

Motivation

Für jedes Retail-Unternehmen ist es ein wichtiges Ziel, Kosten zu reduzieren und Umsätze zu erhöhen, um schlussendlich den Gewinn zu maximieren. Dies fängt beim Einkauf an, geht weiter über eine margenoptimierte Preissetzung und endet mit einer gezielten Kundenansprache.

Im Kundenlebenszyklus gilt es, den Kunden zum richtigen Zeitpunkt mit dem richtigen Angebot zu kontaktieren. Dabei sollen aktive Kunden zu einem weiteren Einkauf motiviert oder inaktive Kunden reaktiviert bzw. deren Abwanderung zu einem Konkurrenten verhindert werden. Der Retailer kann seinen Kunden hierzu vielfältige Angebot machen, bspw. durch individuelle Produktempfehlungen, kundenspezifische Rabattaktionen oder ereignisbasierte Newsletter.

Ziel ist dabei, möglichst solche Kunden auszuwählen, mit denen Umsatz bei möglichst geringen Kosten generiert werden kann. Zu den Kosten zählen dabei nicht nur reine Werbekosten, sondern auch indirekte Kosten, die z.B. dann entstehen, wenn der Retailer aktive Kunden mit einem Rabattgutschein anspricht. Dies führt zu keiner Umsatzsteigerung, da diese Kunden auch ohne Rabattgutschein eingekauft hätten. Weiterhin entstehen bei dem Retailer Kosten, wenn Personen für Werbeaktionen selektiert werden, deren tatsächliche Kaufwahrscheinlichkeit gegen Null tendiert.

„I know that half of marketing is wasted – my problem is that I just don’t know which half.”

John Wanamaker

Zur Lösung dieser Herausforderung benötigt der Retailer somit einen Ansatz, um die richtigen Kunden zum richtigen Zeitpunkt mit dem richtigen Content anzusprechen. STATWORX hat hierzu für einen Kunden aus dem Einzelhandel einen ganzheitlichen Ansatz entwickelt. Auf Basis von Kundenstamm- und Transaktionsdaten haben wir verschiedene state-of-the-art Methoden des Machine Learnings und der künstlichen Intelligenz nutzt, um Kundengruppen individuell und automatisiert auf verschiedenen Kanälen ansprechen zu können. Dadurch konnte das Unternehmen seinen manuellen Aufwand bei der Kundenauswahl und Versendung des Contents signifikant reduzieren und gleichzeitig den der Aktion zugeordneten Umsatz steigern.

Challenge

Aufgrund bisheriger Erfahrungen im Direktmarketing hatte unser Kunde zwei zentrale Herausforderungen identifiziert, die durch die bisherigen verwendeten Methoden nicht zufriedenstellend gelöst werden konnten:

  1. Customer Churn & Retention: Wann und wie sollten inaktive Kunden gezielt angesprochen werden, um eine Abwanderung möglichst effizient zu verhindern? Genauer gesagt, welche Kunden müssen zu einem gegebenen Zeitpunkt kontaktiert und welche Anreize sollte man ihnen für den nächsten Einkauf bieten? (Outbound Marketing)
  2. Next Basket Prediction: Welche Produkte sollten aktiven Kunden empfohlen werden, die sie zu einem Folgekauf anregen können? (Inbound Marketing)

Um diese Fragestellungen modellgetrieben beantworten zu können, bedarf es einer umfangreichen Datenbasis. Für diese müssen alle relevanten Informationen aus den vorliegenden Datenquellen extrahiert, miteinander verknüpft und in geeigneter Form aggregiert werden. So soll eine umfassende zentrale Datenbank auf Kundenebene entstehen, die für die oben genannten Fragestellungen sowie auch weitere Problemstellungen verwendet werden kann. Zu dieser Datenbasis gehören in diesem Fall die Artikel- und Kundenstammdaten, historischen Transaktionsdaten, Kundenaktionsdaten, Standortdaten sowie Informationen aus externen Datenquellen.

Für unseren Kunden war es außerdem von besonderer Relevanz, die sich aus den Fragestellungen ergebenden Schritte möglichst automatisiert ablaufen zu lassen und dementsprechend in die eigene IT-Infrastruktur zu integrieren. Somit müssen alle Schritte von der Datenextraktion & -aufbereitung hin zum Versand der individuellen Newsletter regelmäßig automatisiert ablaufen, bzw. ereignisbasiert angestoßen werden.

Zusätzlich sollte auch die Wartbarkeit und eine manuelle Nutzung der Data Pipeline und der Modelle durch die interne Data Science Abteilung gewährleistet sein. Insbesondere das auf Kundenebene zu aggregierende Data Warehouse soll der Abteilung, über die beiden Problemstellungen hinaus, als Datengrundlage für Ad-hoc-Analysen oder für weitere eigene Modelle und Analysen dienen.

Solution

Die eingangs beschriebenen Fragestellungen unterscheiden sich vor allem in der Art ihrer Komplexität. Bei der Kundenreaktivierung liegt die Herausforderung vor allem in der Entwicklung der Data Pipeline und der Datenaufbereitung. Beim Produkt-Recommender stellt hingegen die Entwicklung der Methodik die größte Herausforderung dar.

Im Bereich der Kundenreaktivierung wird der auf Kundenebene aggregierte Datensatz zunächst dazu verwendet, die Kaufwahrscheinlichkeit aller Kunden für einen definierten Zeitraum in der Zukunft zu ermitteln. Diese Prognose dient dazu, Kunden, die eine sehr hohe Wahrscheinlichkeit für einen Kauf haben, für das weitere Prozedere auszuschließen. Der Grund hierfür ist, dass diese Kunden ohnehin nicht im Rahmen einer Kampagne reaktiviert werden müssen. Genauso können Kunden ausgeschlossen werden, die eine sehr niedrige Kaufwahrscheinlichkeit aufweisen, da eine Reaktivierung dieser Kunden grundsätzlich wenig erfolgsversprechend ist.

Im Anschluss an diesen ersten Schritt wird ein zweites Machine Learning Modell angewendet, das für jeden Kunden individuell aus einer im Vorhinein definierten Auswahl an Rabattgutscheinen den jeweils optimalen Gutschein selektiert. Ferner kann die Menge der zu reaktivierenden Kunden anhand verschiedener Kennzahlen eingeschränkt werden. Die zu reaktivierenden Kunden werden nach Vertriebslinie und Versandart unterteilt und die Mailings bzw. Newsletter inklusive der entsprechenden Rabattgutscheine automatisiert an die Kunden versendet. Daraufhin wird die Aktivität der Kunden im Aktionszeitraum beobachtet und als Trainingsmenge in das zweite Modell eingespeist. Außerdem wird die Kampagne anhand der Aktivierungs- und Reaktionsquoten evaluiert.

Zur Empfehlung weiterer Produkte an aktive Kunden wird ein state-of-the-art Modell aus der aktuellen Forschung genutzt. Das DREAM Modell [2] nutzt rekurrente neuronale Netze (RNN), um die gesamte Kaufhistorie des Kunden berücksichtigen zu können. DREAM erlernt nicht nur die dynamische Repräsentation der Kunden, sondern erfasst auch globale sequentielle Merkmale über alle Warenkörbe hinweg. Diese Darstellung kann die Interessen der Kunden dynamisch, zu verschiedenen Zeitpunkten repräsentieren und mit den globalen sequentiellen Merkmalen aller Warenkörbe des Benutzers im Laufe der Zeit in Verbindung setzen. Hierdurch kann ein deutlich realistischeres Modell zur Produktempfehlung angewendet werden, was sich auch in signifikant besseren Trefferquoten zwischen den vorhergesagten und tatsächlichen Warenkörben widerspiegelt.

Data Warehouse als Basis

Das Data Warehouse bildet die Datenbasis für alle verwendeten Modelle. Es enthält alle Datenpunkte, mit denen die Kaufwahrscheinlichkeiten prognostiziert, Produktempfehlungen erzeugt und verschiedenste Analysen und Visualisierungen erstellt werden können. Im Rahmen der Integration der verschiedenen Datenquellen werden zunächst alle gesperrten und gelöschten Kunden sowie Personen, die der Direktwerbung nicht zugestimmt haben, aus dem Kundenstamm entfernt.

Der Kundenstamm wird durch Kundenkartendaten, die Kundenadressen und die geographischen Informationen der Postleitzahlen angereichert. Darüber hinaus werden Postrückläufer ohne E-Mail-Adresse und/oder ohne E-Mail Opt-in aus dem Datensatz entfernt.

Abschließend werden die Filialinformationen der Stammfiliale der Kunden angefügt. Die Filialinformationen bestehen aus geographischen Informationen, Daten zu den Filialflächen und externen Konsumdaten. Ergänzt werden diese Daten durch die in diesem Projekt berechneten Distanzen zum nächstgelegenen Konkurrenten. Neben den Stammdaten der Kunden werden die Transaktionsdaten zusammengefasst. Jeder verkaufte Artikel wird durch weitere Informationen aus dem Artikelstamm ergänzt und auf Bon-Ebene aggregiert.

Diesem Datensatz können nun die ebenfalls auf Bon-Ebene vorliegenden Informationen aus dem Kundenbonusprogramm hinzugefügt werden. Der Datensatz wird daraufhin auf Kundenebene aggregiert. Von besonderer Bedeutung ist dabei, dass bei den beiden Aggregationsschritten die Kaufhistorie bis auf Artikelebene für die Produktempfehlung erhalten bleibt. Dazu wird eine Spalte erstellt, in der in einer verschachtelten Liste alle Warenkörbe und die darin enthaltenen Artikel eines jeden Kunden aufgelistet sind.

Ergänzend wird die Kauffrequenz pro Kunde berechnet, repräsentiert als die durchschnittliche Anzahl an Tagen zwischen den einzelnen Einkäufen.

Customer Churn & Retention Modell

Basierend auf dem historischen Kaufverhalten wird ein XGBoost-Modell [1] trainiert, um die Wahrscheinlichkeit der Kunden mindestens einen Kauf in den nächsten 3 Monaten zu tätigen, vorhersagen zu können. Das trainierte Modell wird auf alle im Data Warehouse enthaltenen Kunden angewendet. Anschließend können bspw. die Top 5% der Kunden mit den höchsten Kaufwahrscheinlichkeiten aus dem Datensatz ausgeschlossen werden. So wird vermieden, dass ohnehin aktive Kunden, die keine Reaktivierung benötigen, angeschrieben werden und einen Rabattgutschein erhalten. Ebenso werden auch alle Kunden mit einer sehr niedrigen Kaufwahrscheinlichkeit herausgefiltert. Darüber hinaus werden alle Kunden ausgeschlossen, die schon in der vorherigen Mailing Aktion kontaktiert wurden.

Abbildung 1: Prozessdarstellung des Customer Churn & Retention Programmes

Basierend auf der Aktivierung der Kunden, die im Aktionszeitraum der vergangenen Kampagnen kontaktierten wurden, wird ein weiteres XGBoost-Modell trainiert. Dieses Modell sagt die Wahrscheinlichkeit mindestens einen Kauf zu tätigen für verschiedene Rabattgutscheine voraus, für jeden von Modell 1 nicht ausgeschlossenem Kunden, bzw. für eine zufällige Auswahl der nicht ausgeschlossenen Kunden. Die folgende Auswahl der anzuschreibenden Kunden sowie der optimalen Rabatthöhe erfolgt auf Basis des gewünschten Mailing Volumens und des Erwartungswertes des Warenkorbes je Rabattgutschein und Kunde.

Die durch das Modell 1 priorisierte Auswahl an Kunden kann durch die Vorgabe einer Mindestkaufwahrscheinlichkeit und/oder eines Mindesterwartungswertes des Warenkorbes weiter eingeschränkt werden.

Bei der Auswahl der optimalen Rabattkombination, basierend auf dem Erwartungswert, wird gleichzeitig auf die Kaufwahrscheinlichkeit und auf die zu erwartenden Kosten des Gutscheins optimiert. Hierfür wird das durchschnittliche Volumen der historischen Warenkörbe für jeden Kunden individuell berechnet und die vorhergesagte Kaufwahrscheinlichkeit des Kunden und der Rabattkombination dem Modell 2 entnommen. Für Kunden mit weniger als vier Einkäufen im Beobachtungszeitraum wird der durchschnittliche Warenkorb aller betrachteten Kunden eingesetzt.

Next Basket Prediction Modell

Das Modell zur Generierung von Produktempfehlungen nutzt eine ähnliche Data Pipeline wie das Customer Churn & Retention Modell. Zunächst wird die im Data Warehouse vorhandene Kaufhistorie dazu genutzt, das Modell zu trainieren. Anschließend kann das Modell zu jedem beliebigen Zeitpunkt für alle Kunden individuelle Kaufempfehlungen bzw. Vorhersagen über den nächsten Warenkorb ausgeben. Hierbei kann definiert werden wie viele Produkte als Empfehlung ausgegeben werden sollen. Diese Empfehlungen sind nach der Kaufwahrscheinlichkeit absteigend sortiert, sodass auch im Nachhinein noch eine weitere Selektion möglich ist.

Anschließend können nach verschiedenen Regeln diejenigen Kunden ausgewählt werden, die einen Newsletter mit ihrer persönlichen Kaufempfehlung erhalten sollen. Welche Kunden das sind wird mit der Marketingabteilung individuell abgestimmt und laufend angepasst. Auch der Einbezug des ersten Modells zur Berechnung der Kaufwahrscheinlichkeiten aus dem Customer Churn & Retention Modell ist hierbei eine Option.

Abbildung 2: Prozessdarstellung des Empfehlungssystems

Automatisierter Versand

Nachdem die anzuschreibenden Kunden durch das Modell identifiziert wurden, können diese mit dem individuellen Rabattgutschein bzw. der Produktempfehlungen über eine API-Schnittstelle an den Dienstleister übergeben werden, der den E-Mail- und Post-Versand übernimmt.

Im Rahmen des Customer Churn & Retention Modells wird zusätzlich noch einer zufällig ausgewählten Anzahl an Kunden ein ebenso zufälliger Rabattgutschein zugesendet, um einen Vergleich zu dem trainierten Modell zu haben. Beim Produktempfehlungsmodell besteht diese Möglichkeit ebenfalls.

Sobald der Versand abgeschlossen ist, stellt der Dienstleister über die API-Schnittstelle eine Datei zur Verfügung, aus der der Versanderfolg ersichtlich wird. Dadurch kann bei der Evaluation sichergestellt werden, dass auch nur solche Kunden betrachtet werden, die tatsächlich einen Rabattgutschein bzw. eine Kaufempfehlung bekommen haben.

Evaluation

Um den Erfolg des Kundenreaktivierungsprogramms überprüfen zu können und neue Trainingsdaten für Modell 2 zu erhalten, werden die auf Kundenebene aggregierten Daten aus dem Data Warehouse auf die in der letzten Aktion kontaktierten Kunden selektiert. Anschließend wird überprüft, ob die Kunden aktiv waren oder sogar den Rabattgutschein genutzt haben.

Da die Aktivität des Kunden im Beobachtungszeitraum die Zielgröße beider Modelle ist, kann zur Evaluation eine zusätzliche Kontrollgruppe genutzt werden. Für diese wird die Aktivität im Beobachtungszeitraum ebenfalls beobachtet. Somit kann festgestellt werden, ob durch die kundenindividuellen Rabattgutscheine generell die Aktivität der Kunden erhöht werden kann. Genauso können bei der Evaluation auch die durch das Modell ausgewählten Kunden und Rabattgutscheine mit den zufällig ausgewählten Kunden und Rabattgutscheinen verglichen werden, um die Wirksamkeit der Kunden- und Rabattauswahl zu überprüfen.

Für das Empfehlungsmodell muss der Erfolg auf eine andere Weise gemessen werden. Es reicht nicht mehr aus, dass ein Kunde überhaupt einen Kauf im Beobachtungszeitraum tätigt. Vielmehr liegt der Fokus darauf, zu messen, ob der Kunde mindestens ein Produkt der ihm zuvor durch das Modell empfohlenen Produkte bei seinem nächsten Einkauf im Warenkorb liegen hat.

Um dies zu bestimmen, haben wir die sogenannte Hit Rate definiert. Ein Hit liegt vor, wenn der Kunde mindestens ein Produkt aus dem empfohlenen Warenkorb kauft. Die Hit Rate beschreibt demzufolge den Anteil erfolgreicher Empfehlungen (Hits) an der Gesamtzahl der Empfehlungen.

Um auch hier die modellbasierten Hits in das Verhältnis zu zufälligen Hits setzen zu können, wird ebenfalls eine Kontrollgruppe betrachtet. Für diese wurden zwar auch Kaufempfehlungen berechnet, allerdings kein Newsletter dazu versendet. So kann die Hit Rate des Modells mit der Hit Rate in der Kontrollgruppe verglichen und der Erfolg des Modells gemessen werden.

Impact

Mit unserem modellgetriebenen und automatisierten Ansatz konnten im Unternehmen sowohl Prozesse als auch Ergebnisse im Direktmarketing verbessert werden.

Angefangen mit der Integration einer Vielzahl an Datenquellen zu einem Data Warehouse auf Kundenbasis, steht dem Unternehmen nun eine täglich aktualisierte Datenbasis zur Verfügung, die nicht nur für die Customer Churn & Retention und Next Basket Prediction Modelle genutzt wird. Auch für weitere Modelle, Ad-hoc-Analysen und Business Intelligence Anwendungen wird dieses Data Warehouse im Unternehmen eingesetzt.

Durch unseren Ansatz konnte der manuelle Aufwand bei der Ansprache von Kunden auf vielen Ebenen reduziert und oftmals sogar komplett automatisiert werden. Beispiele hierfür sind die automatisierte Identifikation und Auswahl der geeigneten Kunden für eine Rabattaktion oder einen Newsletter mit Produktempfehlungen, die automatisierte Überprüfung der Kunden bezüglich konsistenter Kontaktdaten, Sperrvermerken oder Löschungen, und die automatisierte Versandabwicklung mit einem externen Dienstleister. All diese nun automatisierten Schritte mussten zuvor durch Mitarbeitende manuell und mit erhöhtem Zeitaufwand erledigt werden.

Darüber hinaus gibt es auch Aufgaben, die manuell überhaupt nicht durchführbar sind. Ein Beispiel hierfür ist die individuell auf den Kunden abgestimmte Auswahl von Produktempfehlungen. Hier können nun Newsletter mit einer standardisierten Produktauswahl für alle Kunden durch Newsletter mit einer individuellen Produktauswahl ersetzt werden.

Nicht nur der Aufwand im Direktmarketing konnte reduziert werden, sondern auch die Ergebnisse der verschiedenen Maßnahmen haben sich verbessert. Durch die gezielte Ansprache inaktiver oder selten aktiver Kunden, konnten solche Kunden zurückgewonnen werden, die den Retailer aus den Augen verloren hatten, zur Konkurrenz gewechselt waren oder einen Anreiz benötigten, um wieder beim Retailer einzukaufen. Mithilfe unserer modellgetriebenen Identifikation der zur Ansprache geeigneten Kunden und der Auswahl individuell passender Rabattgutscheine konnten Streuverluste minimiert werden. Einerseits wurden Versandkosten für Kunden eingespart, die auf die Rabattgutscheine gar nicht reagieren und von unserem Modell aussortiert werden. Andererseits wurden auch Kosten für Rabattgutscheine eingespart, die von regelmäßig einkaufenden Kunden eingelöst werden, die auch ohne einen Rabattgutschein Einkäufe getätigt hätten und nun ebenfalls nicht mehr in die Rabattaktionen miteinbezogen werden.

Ferner konnten mit der Bestimmung des gewinnoptimalen Rabattgutscheins individuell je Kunde die Kosten und Gewinne aus den Rabattaktionen selbst weiter optimiert werden.

Nachdem es uns gelungen war mithilfe des Customer Churn & Retention Ansatzes kostenoptimal Kunden zurückzugewinnen, galt es nun diese Kunden auch zu weiteren Käufen anzuregen. Hierbei konnte die Next Basket Prediction dem Unternehmen helfen, automatisiert und individuell die zurückgewonnenen Kunden, aber auch regelmäßig aktive Kunden, interessante Produkte zu präsentieren und so die Kunden weiter regelmäßig zum Besuch des Retailers zu motivieren, zu weiteren Ankäufen anregen und eine tiefergehende Bindung zum Kunden aufzubauen.

Fazit & Ausblick

Mit den beiden modellgetriebenen Ansätzen konnten wir dem Einzelhändler dabei helfen, seine Kundenansprache in den verschiedenen Phasen des Kundenlebenszyklus zu optimieren und automatisieren, bei einer gleichzeitigen Kostensenkung und Umsatzsteigerung.

Durch unseren ganzheitlichen Ansatz steht dem Einzelhändler ein Data Warehouse zur Verfügung, das er einerseits für weitergehende Analysen oder Business Intelligence Anwendungen nutzen kann, mit dem er andererseits aber auch weitere Aufgaben im Marketingbereich durch modellgetriebene Ansätze optimieren und automatisieren kann.

Mit der fortschreitenden Digitalisierung haben die Kunden mittlerweile den Anspruch an die Unternehmen, mit individuellem Content angesprochen zu werden. Dieser Trend wird sich auch in Zukunft fortsetzen, sodass es gilt die im Unternehmen vorhandenen Datenquellen zu nutzen, um diesen Wunsch des Kunden zu erfüllen und ihn seinen Bedürfnissen entsprechend zu kontaktieren.


Quellen

[1] Chen, Tianqi / Guestrin, Carlos (2016) „Xgboost: A scalable tree boosting system“, In: Proceedings of the 22nd ACM SIGKDD international conference on knowledge discovery and data mining, S. 785-794

[2] Yu, Feng, et al. (2016) „A dynamic recurrent model for next basket recommendation“, In: Proceedings of the 39th International ACM SIGIR conference on Research and Development in Information Retrieval, S. 729-732

 

Niklas Junker Niklas Junker Niklas Junker

Netzwerke sind überall. Wir haben soziale Netzwerke wie Facebook, kompetitive Produktnetzwerke oder verschiedene Netzwerke innerhalb einer Organisation. Auch für STATWORX ist es eine häufige Aufgabe, verborgene Strukturen und Cluster in einem Netzwerk aufzudecken und sie für unsere Kunden zu visualisieren. In der Vergangenheit haben wir dazu das Tool Gephi verwendet, um unsere Ergebnisse der Netzwerkanalyse zu visualisieren. Beeindruckt von dieser schönen und interaktiven Visualisierung war unsere Idee, einen Weg zu finden, Visualisierungen in der gleichen Qualität direkt in R zu erstellen und sie unseren Kunden in einer R Shiny App zu präsentieren.

Unsere erste Überlegung war, Netzwerke mit igraph zu visualisieren, einem Paket, das eine Sammlung von Netzwerkanalysetools enthält, wobei der Schwerpunkt auf Effizienz, Portabilität und Benutzerfreundlichkeit liegt. Wir haben es in der Vergangenheit schon in unserem Paket helfRlein für die Funktion getnetwork verwendet. Das Paket igraph kann zwar ansprechende Netzwerkvisualisierungen erstellen, aber leider sind diese jedoch ausschließlich statisch. Um hingegen interaktive Netzwerkvisualisierungen zu erstellen, stehen uns mehrere Pakete in R zur Verfügung, die alle auf Javascript-Bibliotheken basieren.

Unser Favorit für diese Visualisierungsaufgabe ist das Paket visNetwork, das die Javascript-Bibliothek vis.js verwendet und auf htmlwidgets basiert. Es ist mit Shiny, R Markdown-Dokumenten und dem RStudio-Viewer kompatibel. visNetwork bietet viele Anpassungsmöglichkeiten, um ein Netzwerk zu individualisieren, einen schönen Output und eine gute Performance, was sehr wichtig ist, wenn wir den Output in Shiny verwenden möchten. Außerdem ist eine hervorragende Dokumentation hier zu finden.

Gehen wir nun also die Schritte durch, die von der Datenbasis bis hin zur perfekten Visualisierung in R Shiny gemacht werden müssen. Dazu verwenden wir im Folgenden das Netzwerk der Les Misérables Charaktere als Beispiel. Dieses ungerichtete Netzwerk enthält Informationen dazu, welche Figuren in Victor Hugos Roman „Les Misérables“ gemeinsam auftreten. Ein Knoten (engl. Node) steht für eine Figur, und ein Kante (engl. Edge) zwischen zwei Knoten zeigt an, dass diese beiden Figuren im selben Kapitel des Buches auftreten. Das Gewicht jeder Verbindung gibt an, wie oft ein solches gemeinsames Auftreten vorkommt.

Datenaufbereitung

Als erstes müssen wir das Paket mit install.packages("visNetwork") installieren und den Datensatz lesmis laden. Der Datensatz ist im Paket geomnet enthalten.

Um das Netzwerk zwischen den Charakteren von Les Misérables zu visualisieren, benötigt das Paket visNetwork zwei Datensätze. Einen für die Knoten und einen für die Kanten des Netzwerks. Glücklicherweise liefern unsere geladenen Daten beides und wir müssen sie nur noch in das richtige Format bringen.

rm(list = ls())

# Libraries ---------------------------------------------------------------
library(visNetwork)
library(geomnet)
library(igraph)


# Data Preparation --------------------------------------------------------

#Load dataset
data(lesmis)

#Nodes
nodes <- as.data.frame(lesmis[2])
colnames(nodes) <- c("id", "label")

#id has to be the same like from and to columns in edges
nodes$id <- nodes$label

#Edges
edges <- as.data.frame(lesmis[1])
colnames(edges) <- c("from", "to", "width")

Die folgende Funktion benötigt spezifische Namen für die Spalten, um die richtige Spalte zu erkennen. Zu diesem Zweck müssen die Kanten ein Data Frame mit mindestens einer Spalte sein, die angibt, in welchem Knoten eine Kante beginnt (from) und wo sie endet (to). Für die Knoten benötigen wir mindestens eine eindeutige ID (id), die mit den Argumenten from und to übereinstimmen muss.

Knoten:

  • label: Eine Spalte, die definiert, wie ein Knoten beschriftet ist
  • value: Definiert die Größe eines Knotens innerhalb des Netzwerks
  • group: Weist einen Knoten einer Gruppe zu; dies kann das Ergebnis einer Clusteranalyse oder einer Community Detection sein
  • shape: Legt fest, wie ein Knoten dargestellt wird. Zum Beispiel als Kreis, Quadrat oder Dreieck
  • color: Legt die Farbe eines Knotens fest
  • title: Legt den Tooltip fest, der erscheint, wenn du den Mauszeiger über einen Knoten bewegst (dies kann HTML oder ein Zeichen sein)
  • shadow: Legt fest, ob ein Knoten einen Schatten hat oder nicht (TRUE/FALSE)

Kanten:

  • label, title, shadow
  • length, width: Definiert die Länge/Breite einer Kante innerhalb des Netzwerks
  • arrows: Legt fest, wo ein möglicher Pfeil an der Kante gesetzt werden soll
  • dashes: Legt fest, ob die Kanten gestrichelt sein sollen oder nicht (TRUE/FALSE)
  • smooth: Darstellung als Kurve (TRUE/FALSE)

Dies sind die wichtigsten Einstellungen. Sie können für jeden einzelnen Knoten oder jede einzelne Kante individuell angepasst werden. Um einige Konfigurationen für alle Knoten oder Kanten einheitlich einzustellen, wie z.B. die gleiche Form oder Pfeile, können wir später bei der Spezifizierung des Outputs visNodes und visEdges nutzen. Wir werden diese Möglichkeit später noch genauer betrachten.

Zusätzlich wollen wir Gruppen innerhalb des Netzwerks identifizieren und darstellen. Wir werden dazu die Gruppen hervorheben, indem wir den Kanten des Netzwerks Farben hinzufügen. Dafür clustern wir die Daten zuerst mit der Community Detection Methode Louvain und erhalten die neue Spalte group:

#Create graph for Louvain
graph <- graph_from_data_frame(edges, directed = FALSE)

#Louvain Comunity Detection
cluster <- cluster_louvain(graph)

cluster_df <- data.frame(as.list(membership(cluster)))
cluster_df <- as.data.frame(t(cluster_df))
cluster_df$label <- rownames(cluster_df)

#Create group column
nodes <- left_join(nodes, cluster_df, by = "label")
colnames(nodes)[3] <- "group"

Output Optionen

Um einen Eindruck davon zu geben, welche Möglichkeiten wir haben, wenn es um die Design- und Funktionsoptionen bei der Erstellung unseres Output geht, sehen wir uns zwei Darstellungen des Les Misérables-Netzwerks genauer an.

Wir beginnen mit der einfachsten Möglichkeit und geben nur die Knoten und Kanten als Data Frames an die Funktion weiter:

visNetwork(nodes, edges)

Mit dem Pipe-Operator können wir unser Netzwerk mit einigen anderen Funktionen wie visNodes, visEdges, visOptions, visLayout oder visIgraphLayout anpassen:

visNetwork(nodes, edges, width = "100%") %>%
  visIgraphLayout() %>%
  visNodes(
    shape = "dot",
    color = list(
      background = "#0085AF",
      border = "#013848",
      highlight = "#FF8000"
    ),
    shadow = list(enabled = TRUE, size = 10)
  ) %>%
  visEdges(
    shadow = FALSE,
    color = list(color = "#0085AF", highlight = "#C62F4B")
  ) %>%
  visOptions(highlightNearest = list(enabled = T, degree = 1, hover = T),
             selectedBy = "group") %>% 
  visLayout(randomSeed = 11)

visNodes und visEdges beschreiben das allgemeine Aussehen der Knoten und Kanten im Netzwerk. Wir können zum Beispiel die Form aller Knoten festlegen oder die Farben aller Kanten definieren.

Wenn es um die Veröffentlichung in R geht, kann das Rendern des Netzwerks viel Zeit in Anspruch nehmen. Um dieses Problem zu lösen, verwenden wir die Funktion visIgraph. Sie verkürzt die Darstellungszeit, indem sie die Koordinaten im voraus berechnet und alle verfügbaren igraph-Layouts bereitstellt.

Mit visOptions können wir einstellen, wie das Netzwerk reagiert, wenn wir mit ihm interagieren. Zum Beispiel, was passiert, wenn wir auf einen Knoten klicken.

Mit visLayout können wir das Aussehen des Netzwerks festlegen. Soll es ein hierarchisches sein oder wollen wir das Layout mit einem speziellen Algorithmus verbessern? Außerdem können wir einen Seed (randomSeed) angeben, damit das Netzwerk immer identisch aussieht, wenn wir es laden.

Dies sind nur einige Beispielfunktionen, mit denen wir unser Netzwerk anpassen können. Das Paket bietet noch viel mehr Möglichkeiten zur individuellen Anpassung. Weitere Details sind in der Dokumentation zu finden.

Shiny Integration

Um die interaktiven Ergebnisse unseren Kunden zu präsentieren, wollen wir sie in eine Shiny-App integrieren. Deshalb bereiten wir die Daten „offline“ auf, speichern die Knoten- und Kanten-Dateien und erstellen den Output innerhalb der Shiny-App „online“. Hier ist ein einfaches Beispiel für das Schema, das für Shiny verwendet werden kann:

global.R:

library(shiny)
library(visNetwork)

 

server.R:

shinyServer(function(input, output) {
  output$network <- renderVisNetwork({
    load("nodes.RData")
    load("edges.RData")

    visNetwork(nodes, edges) %>%
      visIgraphLayout()
  })
})

ui.R:

shinyUI(
  fluidPage(
    visNetworkOutput("network")
  )
)

 

Der Screenshot unserer Shiny-App veranschaulicht ein mögliches Ergebnis:

Fazit

Neben anderen verfügbaren Paketen zur interaktiven Visualisierung von Netzwerken in R, ist visNetwork unser absoluter Favorit. Es ist ein leistungsstarkes Paket, um interaktive Netzwerke direkt in R zu erstellen und in Shiny zu veröffentlichen. Wir können unsere Netzwerke direkt in unsere Shiny-Anwendung integrieren und sie mit einer stabilen Performance ausführen, wenn wir die Funktion visIgraphLayout verwenden. So benötigen wir keine externe Software wie Gephi mehr.

Habe ich dein Interesse geweckt, deine eigenen Netzwerke zu visualisieren? Dann kannst du gerne meinen Code verwenden oder mich kontaktieren und die Github-Seite des verwendeten Pakets hier besuchen.

Quellen

Knuth, D. E. (1993) „Les miserables: coappearance network of characters in the novel les miserables“, The Stanford GraphBase: A Platform for Combinatorial Computing, Addison-Wesley, Reading, MA

Niklas Junker

Netzwerke sind überall. Wir haben soziale Netzwerke wie Facebook, kompetitive Produktnetzwerke oder verschiedene Netzwerke innerhalb einer Organisation. Auch für STATWORX ist es eine häufige Aufgabe, verborgene Strukturen und Cluster in einem Netzwerk aufzudecken und sie für unsere Kunden zu visualisieren. In der Vergangenheit haben wir dazu das Tool Gephi verwendet, um unsere Ergebnisse der Netzwerkanalyse zu visualisieren. Beeindruckt von dieser schönen und interaktiven Visualisierung war unsere Idee, einen Weg zu finden, Visualisierungen in der gleichen Qualität direkt in R zu erstellen und sie unseren Kunden in einer R Shiny App zu präsentieren.

Unsere erste Überlegung war, Netzwerke mit igraph zu visualisieren, einem Paket, das eine Sammlung von Netzwerkanalysetools enthält, wobei der Schwerpunkt auf Effizienz, Portabilität und Benutzerfreundlichkeit liegt. Wir haben es in der Vergangenheit schon in unserem Paket helfRlein für die Funktion getnetwork verwendet. Das Paket igraph kann zwar ansprechende Netzwerkvisualisierungen erstellen, aber leider sind diese jedoch ausschließlich statisch. Um hingegen interaktive Netzwerkvisualisierungen zu erstellen, stehen uns mehrere Pakete in R zur Verfügung, die alle auf Javascript-Bibliotheken basieren.

Unser Favorit für diese Visualisierungsaufgabe ist das Paket visNetwork, das die Javascript-Bibliothek vis.js verwendet und auf htmlwidgets basiert. Es ist mit Shiny, R Markdown-Dokumenten und dem RStudio-Viewer kompatibel. visNetwork bietet viele Anpassungsmöglichkeiten, um ein Netzwerk zu individualisieren, einen schönen Output und eine gute Performance, was sehr wichtig ist, wenn wir den Output in Shiny verwenden möchten. Außerdem ist eine hervorragende Dokumentation hier zu finden.

Gehen wir nun also die Schritte durch, die von der Datenbasis bis hin zur perfekten Visualisierung in R Shiny gemacht werden müssen. Dazu verwenden wir im Folgenden das Netzwerk der Les Misérables Charaktere als Beispiel. Dieses ungerichtete Netzwerk enthält Informationen dazu, welche Figuren in Victor Hugos Roman „Les Misérables“ gemeinsam auftreten. Ein Knoten (engl. Node) steht für eine Figur, und ein Kante (engl. Edge) zwischen zwei Knoten zeigt an, dass diese beiden Figuren im selben Kapitel des Buches auftreten. Das Gewicht jeder Verbindung gibt an, wie oft ein solches gemeinsames Auftreten vorkommt.

Datenaufbereitung

Als erstes müssen wir das Paket mit install.packages("visNetwork") installieren und den Datensatz lesmis laden. Der Datensatz ist im Paket geomnet enthalten.

Um das Netzwerk zwischen den Charakteren von Les Misérables zu visualisieren, benötigt das Paket visNetwork zwei Datensätze. Einen für die Knoten und einen für die Kanten des Netzwerks. Glücklicherweise liefern unsere geladenen Daten beides und wir müssen sie nur noch in das richtige Format bringen.

rm(list = ls())

# Libraries ---------------------------------------------------------------
library(visNetwork)
library(geomnet)
library(igraph)


# Data Preparation --------------------------------------------------------

#Load dataset
data(lesmis)

#Nodes
nodes <- as.data.frame(lesmis[2])
colnames(nodes) <- c("id", "label")

#id has to be the same like from and to columns in edges
nodes$id <- nodes$label

#Edges
edges <- as.data.frame(lesmis[1])
colnames(edges) <- c("from", "to", "width")

Die folgende Funktion benötigt spezifische Namen für die Spalten, um die richtige Spalte zu erkennen. Zu diesem Zweck müssen die Kanten ein Data Frame mit mindestens einer Spalte sein, die angibt, in welchem Knoten eine Kante beginnt (from) und wo sie endet (to). Für die Knoten benötigen wir mindestens eine eindeutige ID (id), die mit den Argumenten from und to übereinstimmen muss.

Knoten:

Kanten:

Dies sind die wichtigsten Einstellungen. Sie können für jeden einzelnen Knoten oder jede einzelne Kante individuell angepasst werden. Um einige Konfigurationen für alle Knoten oder Kanten einheitlich einzustellen, wie z.B. die gleiche Form oder Pfeile, können wir später bei der Spezifizierung des Outputs visNodes und visEdges nutzen. Wir werden diese Möglichkeit später noch genauer betrachten.

Zusätzlich wollen wir Gruppen innerhalb des Netzwerks identifizieren und darstellen. Wir werden dazu die Gruppen hervorheben, indem wir den Kanten des Netzwerks Farben hinzufügen. Dafür clustern wir die Daten zuerst mit der Community Detection Methode Louvain und erhalten die neue Spalte group:

#Create graph for Louvain
graph <- graph_from_data_frame(edges, directed = FALSE)

#Louvain Comunity Detection
cluster <- cluster_louvain(graph)

cluster_df <- data.frame(as.list(membership(cluster)))
cluster_df <- as.data.frame(t(cluster_df))
cluster_df$label <- rownames(cluster_df)

#Create group column
nodes <- left_join(nodes, cluster_df, by = "label")
colnames(nodes)[3] <- "group"

Output Optionen

Um einen Eindruck davon zu geben, welche Möglichkeiten wir haben, wenn es um die Design- und Funktionsoptionen bei der Erstellung unseres Output geht, sehen wir uns zwei Darstellungen des Les Misérables-Netzwerks genauer an.

Wir beginnen mit der einfachsten Möglichkeit und geben nur die Knoten und Kanten als Data Frames an die Funktion weiter:

visNetwork(nodes, edges)

Mit dem Pipe-Operator können wir unser Netzwerk mit einigen anderen Funktionen wie visNodes, visEdges, visOptions, visLayout oder visIgraphLayout anpassen:

visNetwork(nodes, edges, width = "100%") %>%
  visIgraphLayout() %>%
  visNodes(
    shape = "dot",
    color = list(
      background = "#0085AF",
      border = "#013848",
      highlight = "#FF8000"
    ),
    shadow = list(enabled = TRUE, size = 10)
  ) %>%
  visEdges(
    shadow = FALSE,
    color = list(color = "#0085AF", highlight = "#C62F4B")
  ) %>%
  visOptions(highlightNearest = list(enabled = T, degree = 1, hover = T),
             selectedBy = "group") %>% 
  visLayout(randomSeed = 11)

visNodes und visEdges beschreiben das allgemeine Aussehen der Knoten und Kanten im Netzwerk. Wir können zum Beispiel die Form aller Knoten festlegen oder die Farben aller Kanten definieren.

Wenn es um die Veröffentlichung in R geht, kann das Rendern des Netzwerks viel Zeit in Anspruch nehmen. Um dieses Problem zu lösen, verwenden wir die Funktion visIgraph. Sie verkürzt die Darstellungszeit, indem sie die Koordinaten im voraus berechnet und alle verfügbaren igraph-Layouts bereitstellt.

Mit visOptions können wir einstellen, wie das Netzwerk reagiert, wenn wir mit ihm interagieren. Zum Beispiel, was passiert, wenn wir auf einen Knoten klicken.

Mit visLayout können wir das Aussehen des Netzwerks festlegen. Soll es ein hierarchisches sein oder wollen wir das Layout mit einem speziellen Algorithmus verbessern? Außerdem können wir einen Seed (randomSeed) angeben, damit das Netzwerk immer identisch aussieht, wenn wir es laden.

Dies sind nur einige Beispielfunktionen, mit denen wir unser Netzwerk anpassen können. Das Paket bietet noch viel mehr Möglichkeiten zur individuellen Anpassung. Weitere Details sind in der Dokumentation zu finden.

Shiny Integration

Um die interaktiven Ergebnisse unseren Kunden zu präsentieren, wollen wir sie in eine Shiny-App integrieren. Deshalb bereiten wir die Daten „offline“ auf, speichern die Knoten- und Kanten-Dateien und erstellen den Output innerhalb der Shiny-App „online“. Hier ist ein einfaches Beispiel für das Schema, das für Shiny verwendet werden kann:

global.R:

library(shiny)
library(visNetwork)

 

server.R:

shinyServer(function(input, output) {
  output$network <- renderVisNetwork({
    load("nodes.RData")
    load("edges.RData")

    visNetwork(nodes, edges) %>%
      visIgraphLayout()
  })
})

ui.R:

shinyUI(
  fluidPage(
    visNetworkOutput("network")
  )
)

 

Der Screenshot unserer Shiny-App veranschaulicht ein mögliches Ergebnis:

Fazit

Neben anderen verfügbaren Paketen zur interaktiven Visualisierung von Netzwerken in R, ist visNetwork unser absoluter Favorit. Es ist ein leistungsstarkes Paket, um interaktive Netzwerke direkt in R zu erstellen und in Shiny zu veröffentlichen. Wir können unsere Netzwerke direkt in unsere Shiny-Anwendung integrieren und sie mit einer stabilen Performance ausführen, wenn wir die Funktion visIgraphLayout verwenden. So benötigen wir keine externe Software wie Gephi mehr.

Habe ich dein Interesse geweckt, deine eigenen Netzwerke zu visualisieren? Dann kannst du gerne meinen Code verwenden oder mich kontaktieren und die Github-Seite des verwendeten Pakets hier besuchen.

Quellen

Knuth, D. E. (1993) „Les miserables: coappearance network of characters in the novel les miserables“, The Stanford GraphBase: A Platform for Combinatorial Computing, Addison-Wesley, Reading, MA

Niklas Junker