Werkzeuge der Segmentierung: k means, Latent Class und mehr als RFM

Kurz gesagt

Niveau: Profi

  • RFM sortiert nach Wert zu einem Zeitpunkt. Es enthält keine Bedürfnisse, keinen Kaufanlass und keine Reaktion, deshalb landeten eine Firmenkundin und eine private Schenkende in derselben Zelle 515.
  • k means teilt stetige Werte in feste Gruppen, indem es den quadrierten Abstand zu den Mittelpunkten minimiert. Die Latent Class Analyse passt ein Wahrscheinlichkeitsmodell an Ja oder Nein Antworten an und gibt jedem Kunden eine Wahrscheinlichkeit je Klasse.
  • Wähl die Zahl der Segmente mit Ellenbogen, Silhouette, kleinster Gruppe und dem Geschäft am Tisch, und bestätig sie mit einem zweiten Verfahren. Im Beispiel stimmen k means und LCA bei 93,7 % der Kunden überein.
  • Im Beispiel bringt das kleinste Segment, die Firmenversender mit 7 % der Kundschaft, 41 % des Umsatzes, während RFM 90 % von ihnen als Einmal oder Zweimalkäufer einstufte.

RFM Scoring ist die Segmentierung, die die meisten Shops wirklich betreiben, und es sortiert nach Wert, statt Verhalten zu beschreiben. An Korbwerk, dem erfundenen Shop für Geschenkkörbe in Hamburg aus den letzten beiden Kapiteln, gehe ich k means und Latent Class Analyse durch, mit der Mathematik, lauffähigem Code, der Wahl der Segmentzahl, einem Profil, Prüfungen der Stabilität und einem Zuordnungsskript. Kapitel 14 von 21 der Serie Marketing Analytics.

Die zwei Kundinnen, die RFM für gleich hielt

Im letzten November kamen bei Korbwerk innerhalb einer Stunde zwei Bestellungen herein. Korbwerk ist Lenas erfundener Onlineshop für Geschenkkörbe in Hamburg, zu finden unter korbwerk.example, derselbe Shop wie in den letzten beiden Kapiteln.

Die erste kam von einer Office Managerin in Hamburg: zwölfmal derselbe Korb, zwölf Lieferadressen, ein Firmenname auf der Rechnung. 540 €. Die zweite kam von einer Frau in München, die ihren drei Schwestern je einen Korb schickte, jeder mit eigener Grußkarte. 190 €. Beides waren erste Bestellungen, beide frisch, und beide lagen im obersten Fünftel der Bestellwerte, denn die meisten Bestellungen im Shop sind ein einzelner Korb für rund 40 bis 70 €.

Das RFM Scoring, das Lena als schnellen Gewinn eingerichtet hatte, steckte beide in dieselbe Zelle: Recency 5, Frequency 1, Monetary 5. Die Automatisierung an dieser Zelle schickte beiden im Dezember eine Mail "Willkommen, hier sind 10 % auf deinen nächsten Korb".

Die Office Managerin brauchte keine 10 %. Sie brauchte jemanden, der sie im nächsten Oktober anruft und fragt, wie viele es diesmal sein sollen. Die Frau in München brauchte Mitte April eine Erinnerung, dass bald Muttertag ist. RFM sah zwei Zahlen und ein Verhalten. Es waren zwei Verhaltensweisen, ehrlich gesagt zwei Geschäfte, in einem Shop. In diesem Kapitel geht es um die Werkzeuge, die sie auseinanderhalten.

Korbwerk, die Kundschaft und jede Zahl hier sind erfunden, damit ich jeden Schritt zeigen kann. Die Zahlen stammen aus einer simulierten Kundendatei, und der Code weiter unten gibt genau das aus, was die Tabellen zeigen.

Wo dieses Kapitel in der Serie steht

Das ist Kapitel 14 von 21 meiner Serie Marketing Analytics und das letzte des dritten Teils, der Verfahren für Wechselbeziehungen. Hauptkomponenten und Faktorenanalyse für Marketer hat 18 Verhaltensspalten für 6.200 Kundinnen und Kunden von Korbwerk auf drei Komponentenwerte eingedampft: Volumen, Schenkneigung und Rabattneigung. Segmentierung: Strategie vor Algorithmen hat dafür argumentiert, erst festzulegen, wofür ein Segment da ist, und dann einen Algorithmus anzufassen. Dieses Kapitel lässt die Algorithmen auf diese drei Werte los. Der vierte Teil beginnt mit Den Wert von Marketingkommunikation modellieren. Jede Grundidee, die hier vorkommt, baut die Seite Grundlagen von Grund auf auf.

Das Strategiekapitel arbeitete mit zwei Jahren Bestellungen und 12.400 Kunden. Hier enthält die Datei, wie in Kapitel 12, die 6.200 Kunden mit einer Bestellung in den letzten 14 Monaten. Die Zahlen sind deshalb kleiner, und die Anteile weichen ab.

Was eine gute Segmentierung leisten muss

Vier Dinge, und eine Segmentierung, die an einem davon scheitert, ist gescheitert.

Trennung. Die Segmente liegen bei dem, was Verhalten treibt, weit auseinander. Zwei Segmente, die sich nur ein wenig unterscheiden, bekommen dasselbe Marketing. Sie sind also ein Segment mit einem Strich mittendurch.

Geschlossenheit. Die Kunden innerhalb eines Segments ähneln sich so stark, dass eine Botschaft, ein Angebot und eine Landingpage für die meisten von ihnen funktionieren.

Verständlichkeit. Wer das Mailprogramm betreut, kann jedes Segment in einem Satz beschreiben, ohne Tabelle. Braucht der Satz die Worte "Komponente zwei", fang noch einmal an.

Umsetzbarkeit. Jedes Segment braucht mindestens eine Sache, die du dafür anders machen würdest: Kanal, Angebot, Zeitpunkt oder Produkt. Sonst ist es eine statistische Kuriosität.

Die ersten beiden lassen sich messen, und die Silhouette weiter unten misst beide. Die letzten beiden sind Urteilssache, und genau dort sterben die meisten Segmentierungen leise: wunderschön getrennte Cluster, mit denen niemand etwas anfangen kann.

Ein Beispiel: Die RFM Zelle 515 besteht die ersten beiden Prüfungen auf dem Papier, denn alle darin haben dieselben drei Werte. An der dritten und vierten scheitert sie. Von den 49 Kunden bei Korbwerk mit 515 sind 40 Firmenkunden und neun private Schenkende, und keine einzelne Maßnahme passt zu beiden.

Der Werkzeugkasten in klaren Worten

Hierarchisches Clustering beginnt mit jedem Kunden als eigenem Cluster und verschmilzt immer wieder das nächstgelegene Paar, bis ein einziger Cluster übrig ist. Den entstehenden Baum, das Dendrogramm, schneidest du dort, wo er die gewünschte Zahl an Gruppen ergibt. Die Ward Verknüpfung verschmilzt das Paar, das die Varianz innerhalb der Cluster am wenigsten erhöht. Sie liefert kompakte Gruppen und ist meine Voreinstellung.1 Der Preis: Jeder Schritt prüft alle möglichen Verschmelzungen,1 in Ordnung bei 6.000 Kunden und nicht machbar bei 6 Millionen.

k means wählt kk Mittelpunkte, ordnet jeden Kunden dem nächsten Mittelpunkt zu, schiebt jeden Mittelpunkt auf den Mittelwert seiner Mitglieder und wiederholt das, bis sich nichts mehr ändert.1 Das Verfahren ist schnell, es skaliert, und es ist das, was die meisten meinen, wenn sie "Clustering" sagen. Es hat auch feste Vorstellungen: numerische Variablen auf vergleichbaren Skalen, ungefähr runde Gruppen mit ähnlicher Streuung,1 und es findet kk Cluster, ob die Daten welche enthalten oder nicht.

Latent Class Analyse (LCA) nimmt an, dass die Kundschaft eine Mischung aus wenigen nicht beobachteten Klassen ist, jede mit eigener Wahrscheinlichkeit für jede Antwort, und dass die Variablen innerhalb einer Klasse unabhängig sind.2 Zugehörigkeit ist eine Wahrscheinlichkeit: Eine Kundin gehört zu 92 % zur einen Klasse und zu 8 % zu einer anderen. Ja oder Nein Antworten und Kategorien verarbeitet die LCA von Haus aus, k means kann das nicht.

Gaußsche Mischmodelle tun dasselbe für stetige Variablen: Ellipsen statt Kreisen und eine Wahrscheinlichkeit der Zugehörigkeit statt eines festen Etiketts.3

Entscheidungsbäume sind das Werkzeug fürs Profil, kein Verfahren zur Segmentierung. Ein flacher Baum, der das Segment aus wenigen einfachen Variablen vorhersagt, liefert die kürzeste Beschreibung jeder Gruppe, in Regeln, die du in ein Mailtool tippen kannst.

Ein Beispiel: Die drei Komponentenwerte von Korbwerk sind stetig und bereits standardisiert, das ist Gebiet von k means. Die rohen Merkmale, etwa "Grußkarte bei den meisten Bestellungen" oder "Firma auf der Rechnung", sind Ja oder Nein Antworten, das ist Gebiet der LCA. Dieses Kapitel lässt beide laufen und vergleicht sie.

Der RFM Wert sortiert, er beschreibt nicht

RFM fasst die Vergangenheit eines Kunden in drei Zahlen zusammen: Recency (wie lange die letzte Bestellung her ist), Frequency (wie viele Bestellungen) und Monetary Value (der durchschnittliche Betrag pro Bestellung).4 Lenas Variante teilt jeden Kunden bei allen drei in Fünftel ein und schreibt die drei Werte nebeneinander:

RFMi=100 Ri+10 Fi+Mi\text{RFM}_i = 100\,R_i + 10\,F_i + M_i

Dabei ist RFMi\text{RFM}_i der dreistellige Code für Kunde ii, RiR_i der Recency Wert von 1 bis 5, mit 5 für das jüngste Fünftel, FiF_i der Frequency Wert und MiM_i der Monetary Wert, jeweils von 1 für das unterste bis 5 für das oberste Fünftel. 555 ist die beste Zelle, wer auf 111 steht, ist wahrscheinlich weg. In Fünftel einteilen heißt sortieren und schneiden, wie beim Median, siehe Grundlagen: Median und Modus.

Rechenbeispiel: zwei Kundinnen, eine Zelle

In der simulierten Datei hat das jüngste Fünftel der Kundschaft innerhalb der letzten 46 Tage bestellt. Beide Kundinnen, mit 12 Tagen, bekommen also R=5R = 5.

Die Frequenz ist klumpig. 34 % der Kunden haben in den 14 Monaten genau eine Bestellung, mehr als ein Fünftel, also teilen sie sich alle den niedrigsten Wert. Beide Kundinnen haben eine Bestellung: F=1F = 1.

Das oberste Fünftel nach durchschnittlichem Bestellwert beginnt bei 69,08 €. 540 € und 190 € liegen beide darüber: M=5M = 5.

Also ist RFM=100×5+10×1+5=515\text{RFM} = 100 \times 5 + 10 \times 1 + 5 = 515 für beide. Im Code, mit den Kunden 1 und 2 als den beiden vom Anfang:

import numpy as np, pandas as pd

c = pd.read_csv("hamper_customers.csv").set_index("customer_id")

def fifth(s):                          # 1 für das unterste Fünftel, 5 für das oberste, Gleichstände teilen sich einen Wert
    return np.ceil(5 * s.rank(method="min", pct=True)).astype(int)

c["R"] = fifth(-c.days_since_last)     # weniger Tage seit der letzten Bestellung ergeben einen höheren Wert
c["F"] = fifth(c.orders)
c["M"] = fifth(c.avg_order_value)
c["RFM"] = 100 * c.R + 10 * c.F + c.M
print(c.loc[[1, 2], ["days_since_last", "orders", "avg_order_value", "RFM"]])

Er gibt zweimal 515 aus. Der Code sagt "neue Kundin mit hohem Wert". Er kann nicht sagen, dass die eine eine Firma ist, die für zwölf Büros kauft, und die andere eine Schwester, die für drei Schwestern kauft, denn keine der beiden Tatsachen steckt in den drei Zahlen.

Wie k means funktioniert

k means misst, wie weit ein Kunde von einem Mittelpunkt entfernt ist, mit dem gewöhnlichen geraden Abstand, nur in mehr Dimensionen:

d(xi,μj)=∑v=1V(xiv−μjv)2d(x_i, \mu_j) = \sqrt{\sum_{v=1}^{V} (x_{iv} - \mu_{jv})^2}

Dabei ist d(xi,μj)d(x_i, \mu_j) der Abstand zwischen Kunde ii und dem Mittelpunkt von Cluster jj, xix_i die Zeile mit den Werten des Kunden, μj\mu_j die Zeile des Mittelpunkts, VV die Zahl der Variablen (drei bei Korbwerk), xivx_{iv} der Wert des Kunden bei Variable vv und μjv\mu_{jv} der Wert des Mittelpunkts dort. Quadrierte Differenzen sind der Rohstoff der Varianz, siehe Grundlagen: Streuung, und eine Zahlenzeile ist ein Vektor, siehe Grundlagen: Matrizen.

Der Algorithmus minimiert die gesamte quadrierte Entfernung zwischen jedem Kunden und dem Mittelpunkt seines eigenen Clusters:1

J=∑j=1k∑xi∈Cj∥xi−μj∥2J = \sum_{j=1}^{k} \sum_{x_i \in C_j} \lVert x_i - \mu_j \rVert^2

Dabei ist JJ die Quadratsumme innerhalb der Cluster, kurz WCSS (nach dem englischen within cluster sum of squares), kk die Zahl der Cluster, CjC_j die Menge der Kunden in Cluster jj, xi∈Cjx_i \in C_j heißt "jeder Kunde ii in Cluster jj", μj\mu_j der Mittelpunkt von Cluster jj, also der Mittelwert seiner Mitglieder, und ∥xi−μj∥2\lVert x_i - \mu_j \rVert^2 der quadrierte Abstand aus der Formel oben. Es ist dieselbe Summe quadrierter Abweichungen wie bei der Varianz, nur um den eigenen Mittelwert jedes Clusters, siehe Grundlagen: der Mittelwert und Grundlagen: Streuung.

Der Algorithmus garantiert nur ein lokales Minimum, und das hängt davon ab, wo die Mittelpunkte starten. Deshalb lässt du ihn von vielen Startpunkten laufen und behältst das beste Ergebnis.1

Rechenbeispiel: sechs Kunden von Hand

Sechs Kunden mit je zwei Werten, geschrieben als (Schenkneigung | Volumen): P1 (2 | minus 1), P2 (3 | minus 1), P3 (2 | 0), P4 (minus 1 | 2), P5 (0 | 2), P6 (minus 1 | 1). Zwei Cluster, und ein absichtlich schlechter Start: Die Mittelpunkte liegen auf P1 und P3.

  1. Zuordnen. P1 und P2 liegen am nächsten am ersten Mittelpunkt (Abstände 0 und 1, gegen 1 und 1,41). P3 bis P6 liegen am nächsten am zweiten. P4 zum Beispiel ist 32+32=4,24\sqrt{3^2 + 3^2} = 4{,}24 vom ersten entfernt und 32+22=3,61\sqrt{3^2 + 2^2} = 3{,}61 vom zweiten.
  2. Verschieben. Der erste Mittelpunkt wandert zum Mittelwert von P1 und P2, (2,5 | minus 1). Der zweite wandert zum Mittelwert von P3 bis P6, (0 | 1,25). Mit diesen Gruppen ist J=0,5+8,75=9,25J = 0{,}5 + 8{,}75 = 9{,}25.
  3. Wieder zuordnen. P3 ist jetzt 1,12 vom ersten Mittelpunkt entfernt und 2,36 vom zweiten, also wechselt es. Alle anderen bleiben.
  4. Verschieben. Die Mittelpunkte wandern nach (2,33 | minus 0,67) und (minus 0,67 | 1,67). Die quadrierten Abstände jedes Clusters summieren sich auf 1,33, also ist J=2,67J = 2{,}67.
  5. Wieder zuordnen. Niemand wechselt, also hält der Algorithmus an.

Ein schlechter Start hat hier eine Runde extra gekostet. Auf echten Daten kann ein schlechter Start in einem ganz schlechteren lokalen Minimum enden, deshalb nutzt der Lauf für Korbwerk weiter unten 50 Starts.

k wählen: Ellenbogen und Silhouette

Für die Wahl von kk stütze ich mich auf zwei Maße. Der Ellenbogen trägt JJ für jedes kk auf und sucht die Stelle, ab der ein weiterer Cluster nicht mehr viel bringt. Die Silhouette vergleicht für jeden Kunden, wie nah er an seinem eigenen Cluster liegt und wie nah am nächsten anderen:5

s(i)=b(i)−a(i)max⁡{a(i), b(i)}s(i) = \frac{b(i) - a(i)}{\max\{a(i),\, b(i)\}}

Dabei ist s(i)s(i) die Silhouette von Kunde ii, a(i)a(i) der mittlere Abstand von Kunde ii zu den anderen Mitgliedern seines eigenen Clusters, b(i)b(i) der mittlere Abstand zu den Mitgliedern des nächstgelegenen anderen Clusters und max⁡{a(i),b(i)}\max\{a(i), b(i)\} der größere der beiden, der s(i)s(i) zwischen minus 1 und 1 hält. Nahe 1 heißt gut platziert, nahe 0 heißt auf einer Grenze, unter 0 heißt wahrscheinlich im falschen Cluster. Der Mittelwert von s(i)s(i) über alle Kunden ergibt eine Zahl pro kk, ein gewöhnlicher Durchschnitt, siehe Grundlagen: der Mittelwert und Grundlagen: Verhältnisse und Raten.

Ein Beispiel: Nimm P3 in den beiden fertigen Clustern oben. Seine Abstände zu P1 und P2 sind 1 und 1,41, also ist a=1,21a = 1{,}21. Seine Abstände zu P4, P5 und P6 sind 3,61, 2,83 und 3,16, also ist b=3,20b = 3{,}20. Dann ist s=(3,20−1,21)/3,20=0,62s = (3{,}20 - 1{,}21) / 3{,}20 = 0{,}62. P3 sitzt klar im richtigen Cluster, wenn auch weniger fest als P1, dessen Silhouette 0,74 beträgt.

Rechenbeispiel: k means auf den drei Komponenten von Korbwerk

Die Eingabe sind die drei Komponentenwerte aus Kapitel 12 für alle 6.200 Kunden. Sie sind bereits standardisiert und unkorreliert, damit ist die erste Falle von k means, ungleiche Skalen, schon aus dem Weg. Der Lauf nutzt scikit learn,1 mit kk von 1 bis 8 und je 50 zufälligen Starts:

import numpy as np, pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

Z = pd.read_csv("hamper_components.csv").set_index("customer_id")   # Volumen, Schenkneigung, Rabattneigung
for k in range(1, 9):
    km = KMeans(n_clusters=k, n_init=50, random_state=1).fit(Z)
    sil = silhouette_score(Z, km.labels_) if k > 1 else float("nan")
    print(k, round(km.inertia_), round(sil, 2), np.bincount(km.labels_).min())

Er gibt für jedes kk die WCSS, die mittlere Silhouette und die Größe des kleinsten Clusters aus:

kWCSSMittlere SilhouetteKleinster Cluster
118.590keine6.200
213.6460,341.263
39.0250,391.254
45.6810,45447
54.7700,38431
64.0660,36431
73.5470,34431
83.2790,31425

Quadratsumme innerhalb der Cluster nach Zahl der ClusterDie Quadratsumme innerhalb der Cluster für k means auf 6.200 erfundenen Kunden von Korbwerk fällt von 18.590 bei einem Cluster auf 13.646, 9.025 und 5.681 bei vier und flacht dann ab auf 4.770, 4.066, 3.547 und 3.279 bei acht.WCSS nach Zahl der Cluster05.00010.00015.00020.00018.590113.64629.02535.68144.77054.06663.54773.2798Quadratsumme innerhalb der ClusterZahl der Cluster k

Die waagrechte Achse ist die Zahl der Cluster, die senkrechte die Quadratsumme innerhalb der Cluster. Jeder der ersten drei zusätzlichen Cluster nimmt zwischen 3.300 und 5.000 weg. Der fünfte nur noch 911, und jeder weitere weniger. Der Ellenbogen liegt bei vier.

Silhouette und Größen erzählen dieselbe Geschichte. Zwei Cluster trennen die regelmäßigen Eigenkäufer von allen anderen, richtig und wenig hilfreich. Drei fügen eine rabattgetriebene Gruppe hinzu, lassen die Firmenkunden aber im Cluster der Schenkenden und dehnen ihn. Vier trennen die Firmenkunden ab, die Silhouette erreicht ihr Maximum bei 0,45, und der kleinste Cluster hat 447 Kunden, 7 %, klein, aber echt. Fünf schneiden die Schenkenden allein nach Rabattneigung in zwei, und die Silhouette fällt. Es bleibt bei vier, und das passt zu dem, was laut Strategiekapitel das Geschäft umsetzen kann.

Das Profil

Die Mittelpunkte in Standardeinheiten, wobei 0 der durchschnittliche Kunde ist und 1 eine Standardabweichung darüber:

SegmentVolumenSchenkneigungRabattneigung
A Anlassschenkerminus 0,420,12minus 0,82
B Firmenversender0,592,86minus 0,13
C Selbstgenießer1,58minus 0,82minus 0,08
D Gelegenheitssparerminus 0,58minus 0,261,03

Mittelpunkte in Standardeinheiten sind etwas für die Analyse. Das Geschäft braucht die Rohspalten, gemittelt pro Segment, aus der Bestellhistorie, aus der die Komponenten gebaut wurden:

import joblib
km = KMeans(n_clusters=4, n_init=50, random_state=1).fit(Z)
c = pd.read_csv("hamper_customers.csv").set_index("customer_id")
c["cluster"] = km.labels_
g = c.groupby("cluster")
profile = pd.DataFrame({
    "customers": g.size(),
    "orders_per_year": g.orders.mean() * 12 / 14,           # das Zeitfenster umfasst 14 Monate
    "average_order": g.spend.sum() / g.orders.sum(),
    "gift_message": g.gift_message_share.mean(),
    "company_invoice": g.company_on_invoice.mean(),
    "voucher": g.voucher_share.mean(),
    "december": g.december_share.mean(),
    "revenue_share": g.spend.sum() / c.spend.sum(),
})
print(profile.round(2))
joblib.dump(km, "kmeans_k4.pkl")                            # das Zuordnungsskript nutzt das wieder
SegmentKundenAnteilBestellungen pro JahrDurchschnittliche BestellungGrußkarteFirma auf der RechnungGutschein genutztDezemberUmsatzanteil
A Anlassschenker2.42439 %2,463 €88 %1 %24 %45 %24 %
B Firmenversender4477 %1,31.042 €87 %91 %12 %79 %41 %
C Selbstgenießer1.24120 %6,950 €9 %1 %31 %18 %28 %
D Gelegenheitssparer2.08834 %1,338 €57 %0 %74 %35 %7 %

Grußkarte, Gutschein genutzt und Dezember sind der durchschnittliche Anteil an den Bestellungen jedes Kunden, Firma auf der Rechnung ist der Anteil der Kunden.

Segment A ist der Schwerpunkt des Shops: zwei Fünftel der Kundschaft, eine Grußkarte bei fast jeder Bestellung, zwei oder drei Anlässe im Jahr, wenige Gutscheine. Diese Leute kaufen nach Datum, nicht nach Preis. Ihr Mittelpunkt bei der Schenkneigung liegt nur bei 0,12, weil die Firmenversender diese Achse dehnen, ein Grund mehr, das Rohprofil zu lesen und nicht nur die Mittelpunkte.

Segment B ist 7 % der Kundschaft und 41 % des Umsatzes: 698 Bestellungen zu durchschnittlich 1.042 € ergeben 726.992 € von den 1.770.862 € der Datei. RFM gab 90 % von ihnen einen Frequency Wert von 1 oder 2, weil sie einmal im Jahr bestellen. In einer Rangfolge nach Häufigkeit sehen sie aus wie Gelegenheitskäufer. Es sind die wertvollsten Beziehungen, die der Shop hat.

Segment C verschickt fast nie ein Geschenk. Diese Kunden bestellen fast siebenmal im Jahr für sich selbst, das natürliche Publikum für ein Korbabo. Ihre Bestellungen verteilen sich übers Jahr: Sie warten nicht auf den Ausverkauf.

Segment D ist die Gruppe, für die die Rabattautomatisierung gebaut wurde: ein Drittel der Kundschaft, 7 % des Umsatzes, etwa eine Bestellung im Jahr und ein Gutschein bei drei von vier Bestellungen. Mehr als die Hälfte ihrer Bestellungen trägt trotzdem eine Grußkarte. Der Name "Gelegenheitssparer" ist eine Hypothese, mehr dazu bei den Fallstricken.

Umsatzanteil nach SegmentAnteil am Umsatz aus 14 Monaten beim erfundenen Shop Korbwerk: Anlassschenker 24 %, Firmenversender 41 %, Selbstgenießer 28 %, Gelegenheitssparer 7 %.Umsatzanteil nach Segment0 %12,5 %25 %37,5 %50 %24 %AAnlassschenker41 %BFirmenversender28 %CSelbstgenießer7 %DGelegenheitssparerUmsatzanteil in %Segment

Die waagrechte Achse zeigt die vier Segmente, die senkrechte den Anteil jedes Segments am Umsatz der 14 Monate. Das kleinste Segment nach Köpfen trägt den größten Anteil, und das größte Publikum für Rabatte den kleinsten.

Zurück zu den beiden Kundinnen vom Anfang. Die Office Managerin in Hamburg landet in B. Die Frau in München landet in A. RFM sah zweimal 515. Die Segmentierung sieht einen Firmenkunden, den man im Oktober anruft, und eine Anlassschenkerin, die man im April erinnert. Keine der beiden hätte 10 % bekommen sollen.

Latent Class Analyse: Zugehörigkeit als Wahrscheinlichkeit

Die LCA passt ein Modell an und maximiert seine Likelihood. In Worten: Die Wahrscheinlichkeit für das Antwortmuster eines Kunden ist die Summe über alle Klassen aus der Wahrscheinlichkeit, in dieser Klasse zu sein, mal der Wahrscheinlichkeit dieses Musters innerhalb der Klasse. Innerhalb einer Klasse gelten die Variablen als unabhängig, also ist diese zweite Wahrscheinlichkeit ein schlichtes Produkt:2

L(θ)=∏i=1n∑c=1Kπc∏v=1VP(xiv∣c)L(\theta) = \prod_{i=1}^{n} \sum_{c=1}^{K} \pi_c \prod_{v=1}^{V} P(x_{iv} \mid c)

Dabei ist L(θ)L(\theta) die Likelihood aller Parameter θ\theta zusammen, nn die Zahl der Kunden, KK die Zahl der Klassen, πc\pi_c der Anteil der Kunden in Klasse cc, VV die Zahl der beobachteten Variablen, xivx_{iv} die Antwort von Kunde ii bei Variable vv und P(xiv∣c)P(x_{iv} \mid c) die Wahrscheinlichkeit, dass ein Mitglied von Klasse cc diese Antwort gibt. Multiplizieren für "und" und Addieren für "entweder oder" sind die Grundregeln der Wahrscheinlichkeit, siehe Grundlagen: Wahrscheinlichkeit. In der Praxis maximiert die Software den Logarithmus von LL, der das lange Produkt in eine Summe verwandelt, siehe Grundlagen: Logarithmen.

Nach der Anpassung gibt die Bayes Regel jedem Kunden eine A posteriori Wahrscheinlichkeit für jede Klasse:2

P(c∣xi)=πc∏v=1VP(xiv∣c)∑c′=1Kπc′∏v=1VP(xiv∣c′)P(c \mid x_i) = \frac{\pi_c \prod_{v=1}^{V} P(x_{iv} \mid c)}{\sum_{c'=1}^{K} \pi_{c'} \prod_{v=1}^{V} P(x_{iv} \mid c')}

Dabei ist P(c∣xi)P(c \mid x_i) die Wahrscheinlichkeit, dass Kunde ii bei seinen Antworten xix_i zu Klasse cc gehört. Der Zähler ist der Anteil von Klasse cc mal der Wahrscheinlichkeit dieser Antworten in ihr, der Nenner addiert dieselbe Größe über jede Klasse c′c', damit sich die A posteriori Wahrscheinlichkeiten eines Kunden zu 1 summieren. Es ist die Bayes Regel genau wie in Grundlagen: Wahrscheinlichkeit.

Diese A posteriori Wahrscheinlichkeit ist der praktische Unterschied zu k means. k means sagt "du bist in Cluster D". Die LCA sagt "du bist zu 0,92 D und zu 0,08 A", und die 0,08 sind eine Information, mit der du arbeiten kannst.

Rechenbeispiel: eine A posteriori Wahrscheinlichkeit von Hand

Zwei Klassen und zwei Ja oder Nein Antworten, mit Zahlen zur Veranschaulichung. Klasse A, die Anlassschenker, umfasst 55 % der Kunden: 95 % von ihnen verschicken meist Geschenke, 5 % nutzen bei den meisten Bestellungen einen Gutschein. Klasse D umfasst 45 %: 70 % verschicken meist Geschenke, 95 % nutzen bei den meisten Bestellungen einen Gutschein. Ein Kunde antwortet zweimal mit Ja.

  1. Klasse A: 0,55×0,95×0,05=0,02610{,}55 \times 0{,}95 \times 0{,}05 = 0{,}0261.
  2. Klasse D: 0,45×0,70×0,95=0,29930{,}45 \times 0{,}70 \times 0{,}95 = 0{,}2993.
  3. Die Summe ist 0,32540{,}3254.
  4. A posteriori: P(A)=0,0261/0,3254=0,08P(A) = 0{,}0261 / 0{,}3254 = 0{,}08 und P(D)=0,2993/0,3254=0,92P(D) = 0{,}2993 / 0{,}3254 = 0{,}92.

Wer verschenkt und Gutscheine nutzt, ist sehr wahrscheinlich ein Gelegenheitssparer, aber einer von zwölf Kunden mit diesem Muster gehört zu den Schenkenden. Das sind die "0,92 D und 0,08 A" von oben.

Die Zahl der Klassen mit dem BIC wählen

Mehr Klassen erhöhen die Likelihood immer, also braucht die LCA eine Strafe für Komplexität. Das bayessche Informationskriterium, das BIC, liefert sie, und das Modell mit dem niedrigsten BIC gewinnt:26

BIC=−2ln⁡L+pln⁡n\text{BIC} = -2 \ln L + p \ln n

Dabei ist ln⁡L\ln L der natürliche Logarithmus der maximierten Likelihood, pp die Zahl der freien Parameter (die Klassenanteile plus jede Antwortwahrscheinlichkeit je Klasse) und nn die Zahl der Kunden. Der erste Term belohnt die Anpassung, der zweite berechnet jeden Parameter, und zwar umso teurer, je größer die Datei. Den Logarithmus erklärt Grundlagen: Logarithmen.

Ein Beispiel mit dem Modell mit vier Klassen von unten: Die Log Likelihood ist minus 17.632,67, es gibt 31 freie Parameter und 6.200 Kunden. Also ist BIC=2×17.632,67+31×ln⁡6.200=35.265,34+31×8,732=35.536,04\text{BIC} = 2 \times 17.632{,}67 + 31 \times \ln 6.200 = 35.265{,}34 + 31 \times 8{,}732 = 35.536{,}04.

Rechenbeispiel: Latent Class Analyse als zweite Meinung

Um zu prüfen, dass k means keine ordentlichen Kreise auf Rauschen gezeichnet hat, passe ich dieselben 6.200 Kunden noch einmal mit der LCA an, auf kategorialen Fassungen der Rohspalten: überwiegend Geschenkbestellungen, Firma auf der Rechnung, Gutschein bei den meisten Bestellungen, überwiegend Bestellungen im Dezember, drei oder mehr Bestellungen (jeweils Ja oder Nein) und die durchschnittliche Bestellung in drei Bändern. "An eine andere Adresse geliefert" bleibt draußen, weil es fast dasselbe sagt wie die Grußkarte und die Annahme der Unabhängigkeit brechen würde.

Wer mit R arbeitet, hat das Paket poLCA.2 In Python ist die Schleife für Expectation Maximization kurz genug, um sie auszuschreiben, und sie zeigt die beiden Formeln oben bei der Arbeit:

c = pd.read_csv("hamper_customers.csv").set_index("customer_id")
items = pd.DataFrame({
    "gift": c.gift_message_share >= 0.5,
    "company": c.company_on_invoice == 1,
    "voucher": c.voucher_share >= 0.5,
    "december": c.december_share >= 0.5,
    "repeat": c.orders >= 3,
    "basket": np.digitize(c.avg_order_value, [50, 250]),   # unter 50 €, 50 bis 250 €, über 250 €
}).astype(int)
H = [np.eye(items[v].max() + 1)[items[v]] for v in items]   # eine Spalte pro Antwortstufe

def lca(H, K, starts=10, iters=200, seed=0):
    rng = np.random.default_rng(seed)
    best = None
    for _ in range(starts):
        pi = np.full(K, 1 / K)
        theta = [rng.dirichlet(np.ones(h.shape[1]), K) for h in H]   # P(Antwort | Klasse)
        for _ in range(iters):
            logp = np.log(pi) + sum(h @ np.log(t).T for h, t in zip(H, theta))
            ll = np.logaddexp.reduce(logp, axis=1)                    # Logarithmus der Summe über die Klassen
            post = np.exp(logp - ll[:, None])                         # Bayes: A posteriori je Klasse
            pi = post.mean(axis=0)
            theta = [np.clip(post.T @ h / post.sum(axis=0)[:, None], 1e-9, 1) for h in H]
        if best is None or ll.sum() > best[0]:
            best = (ll.sum(), pi, theta, post)
    return best

n, fits = len(items), {}
for K in range(2, 7):
    ll, pi, theta, post = fits[K] = lca(H, K)
    p = (K - 1) + K * sum(h.shape[1] - 1 for h in H)            # freie Parameter
    print(K, round(-ll), p, round(-2 * ll + p * np.log(n)), np.bincount(post.argmax(1), minlength=K).min())

Wie k means findet auch diese Schleife nur ein lokales Maximum, also startet sie zehnmal und behält das beste Ergebnis.2 Sie gibt aus:

KlassenNegative Log LikelihoodParameterBICKleinste Klasse
220.7541541.6402.108
318.7012337.603430
417.6333135.536430
517.6283935.597430
617.6284735.666224

Das BIC erreicht seinen Tiefpunkt bei vier Klassen. Eine fünfte Klasse kauft fünf Punkte Log Likelihood und bezahlt dafür 61 Punkte BIC.

Dann der Vergleich. Die Klassennummern der LCA sind willkürlich, also werden die Klassen den Clustern von k means nach ihrem Inhalt zugeordnet, nicht nach ihrer Nummer:

from scipy.optimize import linear_sum_assignment
post = fits[4][3]
table = pd.crosstab(km.labels_, post.argmax(1))
rows, cols = linear_sum_assignment(-table.values)              # beste Zuordnung eins zu eins
print(table, round(table.values[rows, cols].sum() / n, 3))

93,7 % der Kunden, 5.808 von 6.200, landen in der passenden Klasse. Von den 392, die wechseln, wechseln 284 zwischen A und D: Anlassschenker, die Gutscheine genutzt haben, oder Gelegenheitssparer, die Grußkarten geschrieben haben. Die A posteriori Wahrscheinlichkeiten sind sich einig. Bei 93,6 % der Kunden liegt die größte über 0,9, bei 4,6 % zwischen 0,7 und 0,9, und bei 111 Kunden, 1,8 %, bei 0,7 oder darunter. 84 dieser 111 liegen zwischen A und D. Diese Grenze ist echt. k means versteckt sie nur, indem es einen harten Strich hindurchzieht.

Welches Werkzeug für welche Aufgabe

Ein Werkzeug für die Segmentierung wählenEin Entscheidungsablauf von oben nach unten: nur sortieren heißt RFM, kategoriale Eingaben heißen Latent Class Analyse, stetige Werte heißen k means oder ein Gaußsches Mischmodell, und jeder Weg endet mit einem zweiten Verfahren als Prüfung.Aufschreiben, wofür die Segmente dasindNur sortieren, wen du zuerstansprichst?jaJa: RFM reichtneinNein: die Eingaben ansehenÜberwiegend Ja oder Nein Antwortenund Kategorien?jaJa: Latent Class AnalyseneinNein: k means auf stetigen Werten, oderein Gaußsches Mischmodell für weicheZugehörigkeitEin zweites Verfahren als Prüfunglaufen lassenÜbereinstimmung von 75 bis 80 % odermehr: Die Segmente stecken in den Daten

Der Ablauf liest sich von oben nach unten: zuerst der Zweck, dann entscheiden die Eingaben über das Verfahren. Meine Regel: k means, wenn die Eingaben stetig sind und schon zu Komponenten bereinigt, LCA, wenn sie überwiegend Ja oder Nein Antworten, Umfragefragen oder Kategorien sind, ein Gaußsches Mischmodell für weiche Zugehörigkeit bei stetigen Daten. Was du auch wählst, lass eins der anderen als Prüfung laufen. Eine Übereinstimmung über 75 bis 80 % zwischen zwei Verfahren ist der stärkste Beleg, den ich kenne, dass die Segmente in den Daten leben und nicht im Algorithmus. Die 93,7 % von Korbwerk liegen bequem darüber.

Was RFM nicht sieht und Segmente nach Verhalten schon

RFM ist eine gute Rangfolge des Werts zu einem Zeitpunkt, das richtige Werkzeug für "wen spreche ich zuerst an", wenn das Budget für eine einzige Aussendung reicht. Als Segmentierung scheitert es aus drei Gründen, die in seiner Definition liegen.

Es enthält keine Bedürfnisse. Recency, Frequency und Monetary Value sagen, was passiert ist, nicht warum. Hinter identischen Werten können eine Hochzeit, ein Trauerfall, eine Vertragsverlängerung oder ein ganz normaler Dienstag stecken.

Es enthält keinen Kaufanlass. Wer verschenkt, kauft, weil ein Datum näher rückt, eine Firma, weil ein Budgetjahr endet, wer für sich kauft, weil der Kühlschrank leer ist. Ein Frequency Wert macht alle drei Kalender platt.

Es enthält keine Reaktion. Was hat jede Gruppe getan, als der Shop zuletzt einen Rabatt, eine Produktgeschichte oder eine Erinnerung verschickt hat? Mit einem Segmentfeld am Kundendatensatz wird das zu einer einfachen Abfrage.

Ein Beispiel, mit Zahlen, die Annahmen dieses Beispiels sind und keine Ergebnisse der Simulation: D klickt Rabattmails dreimal so oft wie A, A klickt die Mail "In drei Wochen ist Muttertag" häufiger als alle anderen, und B öffnet überhaupt keine Marketingmails, während ein Anruf im Oktober bei rund 60 % von ihnen eine Nachbestellung bringt. Nichts davon lässt sich messen, solange das Segment nicht existiert.

Segmente nach Verhalten liefern dir den Auslöser, das Bedürfnis und die Reaktion, und genau das brauchst du, um verschiedenen Menschen verschiedenes Marketing zu schreiben, der Kern von Segmentierung ist keine Demografie.

So läuft es in der Praxis

Daten. Eine Zeile pro Kunde aus 12 bis 24 Monaten Bestellungen: gekaufte Kategorien, ob Liefer und Rechnungsadresse abweichen (nicht die Adressen selbst), Grußkarten, Gutscheine, das Firmenfeld und, falls vorhanden, das Verhalten bei Mails. In einem Solidus Shop liegt all das in den Tabellen spree_orders, spree_line_items, spree_addresses und spree_adjustments.7 Ein paar Hundert Kunden sind zu wenige, damit k means etwas bedeutet. Ich würde ab etwa tausend anfangen und dem Ergebnis ab etwa fünftausend trauen.

Schritte. Die Tabelle mit 10 bis 20 Verhaltensvariablen bauen. Standardisieren oder auf Komponenten verdichten. k means für kk von 2 bis 8 mit vielen Starts laufen lassen. LCA oder ein Gaußsches Mischmodell als zweite Meinung anpassen. kk wählen, mit dem Geschäft am Tisch. Profil erstellen, benennen, das Zuordnungsskript schreiben und das Segmentfeld in den Shop und ins Mailtool laden.

Prüfungen, bevor du dem Ergebnis traust. k means mit 20 verschiedenen Seeds neu anpassen und jedes Ergebnis mit dem ursprünglichen über den adjustierten Rand Index vergleichen, der bei identischen Gruppierungen 1 ist und bei zufälliger Übereinstimmung nahe 0.8 Unter 0,9 ist die Lösung instabil, und ich würde sie nicht ausliefern. Dann der Bootstrap: Kunden mit Zurücklegen neu ziehen, neu anpassen, alle zuordnen, vergleichen.9 Ich will einen Median des adjustierten Rand Index über 0,7.

from sklearn.metrics import adjusted_rand_score
ref = km.labels_
seeds = [adjusted_rand_score(ref, KMeans(4, n_init=10, random_state=s).fit(Z).labels_) for s in range(20)]
rng = np.random.default_rng(0)
boot = []
for b in range(100):                                   # Kunden neu ziehen, neu anpassen, alle zuordnen
    sample = Z.iloc[rng.integers(0, len(Z), len(Z))]
    boot.append(adjusted_rand_score(ref, KMeans(4, n_init=10, random_state=b).fit(sample).predict(Z)))
print(round(min(seeds), 3), round(np.median(boot), 3), round(np.percentile(boot, 5), 3))

Er gibt 0.999 0.991 0.978 aus: Der schlechteste der 20 Seeds stimmt fast perfekt überein, und selbst die schwächsten 5 % der Bootstrap Läufe bleiben nahe 0,98. Zwei weitere Prüfungen brauchen Zeit statt Code. Eine zeitliche Holdout Prüfung: auf den ersten zehn Monaten anpassen, die letzten vier zuordnen und schauen, ob sich das Profil noch genauso liest. Vorhersagekraft: Sagt die Zugehörigkeit etwas voraus, das das Modell nie gesehen hat, etwa die Reaktion auf die Kampagne im letzten Frühjahr? Segmente, die außerhalb ihrer eigenen Eingaben nichts vorhersagen, sind eine Beschreibung, kein Werkzeug.

Zuordnung. Das Zuordnungsskript ist kurz, und es muss das angepasste Modell wiederverwenden statt neu anzupassen:

km = joblib.load("kmeans_k4.pkl")                      # Mittelpunkte beim Anpassen eingefroren
names = {0: "A", 3: "B", 2: "C", 1: "D"}               # nach dem Profil zugeordnet, nicht nach der Nummer
Z = pd.read_csv("hamper_components.csv").set_index("customer_id")   # die Werte dieses Monats
out = pd.DataFrame(index=Z.index)
out["segment"] = [names[c] for c in km.predict(Z)]
out["distance"] = km.transform(Z).min(axis=1)          # weit weg von jedem Mittelpunkt: zur Prüfung markieren
out.to_csv("customer_segments.csv")

Im Monat der Anpassung bildet es das Profil exakt ab: 2.424 in A, 447 in B, 1.241 in C, 2.088 in D. Das eine Prozent, das am weitesten von jedem Mittelpunkt entfernt liegt, sitzt mehr als 1,98 Standardeinheiten weg, und diese Kunden sehe ich mir von Hand an. Im Betrieb kommen die Komponentenwerte des Monats aus dem Skalierer und den Gewichten, die in Kapitel 12 gespeichert wurden, nie aus einer neuen Anpassung.

Monatlich neu zuordnen, aber nicht monatlich neu anpassen: Eine neue Anpassung verschiebt die Mittelpunkte und benennt alle neu, und das bricht jeden Kampagnenbericht, der ein Segment beim Namen nennt. Ein oder zweimal im Jahr neu anpassen, als kleines Projekt mit einer Wanderungstabelle. Für einen Shop dieser Größe dauert die ganze Arbeit zwei bis drei Wochen, die Hälfte davon an der Kundentabelle.

Fallstricke

Unskalierte Eingaben. Der Bestellwert in Euro neben einem Merkmal Grußkarte mit 0 oder 1: k means clustert nach Euro und nach sonst nichts. Standardisieren, oder besser, auf Komponenten clustern.

Kreise, wo die Daten keine haben. Ist die wahre Struktur eine lange, schmale Gruppe, etwa Eigenkäufer entlang eines Gefälles beim Ausgeben, schneidet k means sie in zwei. Mischmodelle mildern das, und eine Silhouette je Cluster zeigt es meistens.

RFM neu erfinden. Dominieren Ausgaben und Häufigkeit die Variablen fürs Clustering, heißen die Cluster am Ende "hoher, mittlerer, niedriger Wert", und du hast RFM mit mehr Schritten gebaut. Halt die Wertvariablen aus dem Clustering heraus und nutz sie danach fürs Profil. Deshalb ist der Umsatzanteil von Segment B ein Ergebnis und keine Eingabe.

Zu viele Segmente. Jedes Segment braucht ein Kreativbriefing, eine Variante der Landingpage, eine Mailstrecke und eine verantwortliche Person. Vier sind für ein kleines Team zu schaffen. Acht sind eine Tabelle, die niemand öffnet.

Starre Zugehörigkeit. Menschen ändern sich. Eine Kundin aus D, die dreimal zum vollen Preis kauft, ist jetzt eine C oder eine A. Monatlich zuordnen und eine Wanderungstabelle führen. Ein gesundes Programm bringt Menschen von D nach A und von A nach B.

Namen werden zu Tatsachen. "Gelegenheitssparer" ist eine Hypothese über 2.088 Menschen, entstanden aus drei Zahlen. Manche davon verschenken und haben den Shop über eine Gutscheinseite gefunden und würden für einen Korb, dem sie vertrauen, gern den vollen Preis zahlen. Teste den Namen: Schick der Hälfte von D eine Produktgeschichte zum vollen Preis statt eines Gutscheins und miss das Ergebnis.

Die LCA hat zwei eigene. Vertauschte Etiketten: Klasse 1 in einem Lauf ist Klasse 3 im nächsten, also ordne Klassen nach ihrem Profil zu, nie nach ihrer Nummer.2 Lokale Unabhängigkeit: Zwei fast doppelte Merkmale, wie "Grußkarte" und "an eine andere Adresse geliefert", brechen die Annahme und erfinden gern zusätzliche Klassen. Lass eins weg oder leg beide zusammen, wie oben.

Wie ich das für Kunden mache

Ich brauche Lesezugriff auf die Bestelldatenbank oder einen Export davon, 12 bis 24 Monate, dazu das Verhalten bei Mails, falls es erfasst ist. Nichts über das hinaus, was der Shop schon hat, und nie die Adressen selbst.

Es beginnt mit dem kostenlosen Workshop, in dem wir festlegen, wofür die Segmente da sind und welche zwei oder drei Maßnahmen das Geschäft für jedes realistisch umsetzen könnte. Danach zwei Wochen echte Arbeit auf meine Rechnung: die Kundentabelle, die Komponenten, k means und LCA nebeneinander, die Prüfungen auf Stabilität, das Profil, die Namen. Du kannst jederzeit aussteigen, und der schriftliche Plan gehört dir.

Was du bekommst:

  • Eine Kundentabelle mit einem Segment und einer Sicherheit für jeden Kunden, geladen in deinen Shop und dein Mailtool.
  • Ein Profil auf einer Seite je Segment, geschrieben für die Menschen, die damit arbeiten.
  • Ein Entscheidungspapier mit der Zahl, auf die es ankommt (im Beispiel: 7 % der Kundschaft bringen 41 % des Umsatzes und werden wie Einmalkäufer behandelt), mit Fehlermarge und Risiko.
  • Das Zuordnungsskript und ein Dashboard, das eine Frage beantwortet: Wie viele Kunden sind diesen Monat in jedem Segment, und woher sind sie gewandert?

Danach, wenn du willst, übernehme ich die Aktivierung: eine Kundenliste je Segment im Shop, im Mailtool und auf den Werbeplattformen, mit der Anrufliste für B im Oktober, der Erinnerung für A im April, dem Aboangebot für C und Lookalike Audiences, die nur aus A und B gespeist werden, denn aus der ganzen Datei gespeist würden sie vor allem mehr D finden.

Deine Rohdaten bleiben deine, und die Regeln für Code und Modelle stehen in den Bedingungen für Analytics und Data Science. Die Methode gehört zu Data Science, die Aktivierung zu Performance Marketing, und die Honorare stehen auf der Preisseite.

Fragen, bevor du eine Segmentierung abnimmst

  • Welche Variablen wurden fürs Clustering verwendet, und waren Ausgaben und Häufigkeit darunter?
  • Wie wurde die Zahl der Segmente gewählt, und was sagten die Silhouette und ein zweites Verfahren?
  • Lässt sich jedes Segment in einem Satz beschreiben, ohne auf eine Tabelle zu schauen?
  • Was macht das Geschäft für jedes Segment anders, und wer ist dafür verantwortlich?
  • Wie stabil sind die Segmente beim Neuziehen und über die Zeit?
  • Wie sieht der Plan für die Neuzuordnung aus, und wie wird Wanderung zwischen Segmenten sichtbar?
  • Welche Segmentnamen sind Hypothesen, die noch getestet werden müssen?

Die Serie ist von Mike Grigsbys Marketing Analytics inspiriert.10 Die Erklärungen, Beispiele und Zahlen hier sind meine eigenen.

Footnotes

  1. Entwicklerinnen und Entwickler von scikit learn, Clustering (Abschnitte zu k means, hierarchischem Clustering und dem Silhouettenkoeffizienten), Benutzerhandbuch von scikit learn, https://scikit-learn.org/stable/modules/clustering.html

  2. Drew A. Linzer und Jeffrey B. Lewis, poLCA: An R Package for Polytomous Variable Latent Class Analysis, Journal of Statistical Software, Band 42, Heft 10, 2011, https://www.jstatsoft.org/article/view/v042i10

  3. Entwicklerinnen und Entwickler von scikit learn, Gaussian mixture models, Benutzerhandbuch von scikit learn, https://scikit-learn.org/stable/modules/mixture.html

  4. Peter S. Fader, Bruce G. S. Hardie und Ka Lok Lee, RFM and CLV: Using Iso value Curves for Customer Base Analysis, Journal of Marketing Research, 2005 (Arbeitspapier der Autoren), https://www.brucehardie.com/papers/rfm_clv_2005-02-16.pdf

  5. Peter J. Rousseeuw, Silhouettes: a graphical aid to the interpretation and validation of cluster analysis, Journal of Computational and Applied Mathematics, Band 20, 1987, S. 53 bis 65, https://linkinghub.elsevier.com/retrieve/pii/0377042787901257

  6. Gideon Schwarz, Estimating the Dimension of a Model, The Annals of Statistics, Band 6, Nr. 2, 1978, S. 461 bis 464, https://projecteuclid.org/journals/annals-of-statistics/volume-6/issue-2/Estimating-the-Dimension-of-a-Model/10.1214/aos/1176344136.full

  7. Mitwirkende von Solidus, Datenbankschema des Kerns (spree_orders, spree_line_items, spree_addresses, spree_adjustments), Quellcode von Solidus auf GitHub, https://github.com/solidusio/solidus/blob/main/core/db/migrate/20160101010000_solidus_one_four.rb

  8. Lawrence Hubert und Phipps Arabie, Comparing partitions, Journal of Classification, Band 2, 1985, S. 193 bis 218, https://link.springer.com/article/10.1007/BF01908075

  9. Christian Hennig, Cluster wise assessment of cluster stability, Computational Statistics and Data Analysis, 2007, https://linkinghub.elsevier.com/retrieve/pii/S0167947306004622

  10. Mike Grigsby, Marketing Analytics: A Practical Guide to Improving Consumer Insights Using Data Techniques, Kogan Page, 2022, ISBN 9781398608191, https://www.netgalley.co.uk/catalog/book/267990

Wenn dein Shop auf RFM Stufen läuft oder auf Segmenten, die jemand vor drei Jahren in einem Workshop benannt hat, bring die Bestellungen der letzten zwei Jahre in meinen kostenlosen Workshop mit. Wir legen fest, wofür die Segmente da sind, dann stecke ich zwei Wochen Arbeit auf meine Rechnung hinein: die Kundentabelle, k means und Latent Class Analyse nebeneinander und eine ehrliche Antwort, wie viele echte Gruppen nach Verhalten darin stecken und was jede wert ist.