Produktempfehlung
Produktempfehlung ist ein KI-Modell zur Produktempfehlung pro Kunde auf Basis historischer Käufe.
Aus Kaufdaten werden Trainingsbeispiele erzeugt (gekauft = positiv, nicht gekauft = negativ), ein Modell trainiert und anschließend für einen Kunden eine Top-N-Liste empfohlener Produkte berechnet.
Das Modell kann sowohl zeitgesteuert (Training) als auch AdHoc (Vorhersage für eine CustomerId) ausgeführt werden.
Konzept
Datenbasis
Als Quelle dient eine Abfrage (Query) auf Verkaufs-/Belegdaten. Die wichtigsten Felder werden der Modelllogik zugeordnet:
- CustomerId (Kunde)
- ProductId (Produkt)
- ProductFamily (Warengruppe/Produktfamilie)
- Timestamp (Kaufdatum für Zeitfilter)
- optional: Industry (Branche)
- optional: Country (Land)
Die Quelldaten werden in einer Support-DB zwischengespeichert, sodass Training und Aggregationen performant laufen.
Features (Eingangsmerkmale)
Pro (Kunde, Produkt)-Kombination werden folgende Merkmale genutzt:
- Kunden-ID (kategorisch, OneHot)
- Branche (kategorisch, OneHot)
- Land (kategorisch, OneHot)
- Produkt-ID (kategorisch, OneHot)
- Produktfamilie-ID (kategorisch, OneHot)
- CustomerBoughtFamily (bool → float)
Ob der Kunde diese Familie bereits gekauft hat. - CustomerFamilyPurchaseCount (float)
Anzahl der Käufe dieser Familie durch den Kunden.
Hinweis: CustomerId und ProductId als OneHot können zu sehr guten Offline-Metriken führen, weil das Modell bekannte Kunden/Produkte “wiedererkennt”. Für realistische Qualitätsmessung sind gruppierte oder zeitbasierte Splits sinnvoll (siehe Abschnitt “Training & Metriken”).
Negative Beispiele (Negativ-Sampling)
Da echte “Nicht-Käufe” in der Regel nicht explizit vorliegen, werden Negativbeispiele synthetisch erzeugt:
- Popularität: Negative kommen aus häufig gekauften Produkten (gewichtete Ziehung).
- Assoziierte Produktfamilien: Negative kommen aus Produkten aus assoziierten Familien (Co-Occurrence auf Familienebene), mit Popularität als Fallback.
Einstellbare Parameter / Eigenschaften
Quelldaten
Quelldaten aktualisieren
Wenn aktiv, werden die zwischengespeicherten Quelldaten (model{ID}_sourcedata) beim Ausführen aktualisiert.
Trainingseinstellungen
Verfahren für Negativbeispiele
Steuert, wie Negativbeispiele erzeugt werden:
- Popularität
Negatives werden aus den beliebtesten Produkten gezogen. - Assoziierte Produktfamilien
Zusätzlich wird aus Familien-Assoziationen gezogen (Land-spezifisch, sonst global). Kunde kauft aus Familie A und Familie B.
Zeitspanne für die Datenauswahl
Begrenzt die Positivbeispiele (Käufe) auf einen Zeitraum ab heute − Wert in Tagen.
Wenn im Zeitraum keine Daten gefunden werden, erfolgt ein Fallback ohne Zeitfilter.
Maximale Anzahl an Datensätzen für das Trainingsmodell
Maximale Anzahl geladener Positivbeispiele (Käufe) für das Training.
Die Anzahl an Trainingsdaten muss begrenzt sein, damit der Ressourceneinsatz kontrollierbar bleibt und das Ergebnis nicht leidet.
Bei 500.000 Käufen und 5 negativen Beispielen ergeben sich 3.000.000 Trainingsdatensätze, was für ein ausgewogenes Trainingsmodell sorgt.
Maximale Anzahl an negativen Beispielen je Kauf
Anzahl Negativbeispiele, die pro Positivbeispiel erzeugt werden.
Poolgröße für populäre Produkte
Größe des Popularitäts-Pools:
- beeinflusst Negativ-Sampling (PopularPool / Fallback)
- beeinflusst Kandidaten-Erzeugung für Vorhersage (Auffüllen mit populären Produkten)
Vorhersageeinstellungen
Maximale Anzahl an Vorhersagen
Anzahl der zurückgegebenen Empfehlungen (Top-N). Je nach Datenlage können auch weniger Ergebnisse entstehen.
Vorhersagen zwischenspeichern
Wenn aktiv:
- Vorhersagen werden in
model{ID}_predictionsgespeichert (Zwischenspeicher und Log) - spätere Aufrufe können gespeicherte Vorhersagen wiederverwenden
- ein erneutes Training löscht zwischengespeicherte Vorhersagen
Quelle für Produktdaten
Optionales Schemaobjekt (Produkt-Stammdaten), um Vorhersagen um zusätzliche Spalten aus dem empfohlenen Produkt anzureichern.
Suche für Produktdaten
Filter (templated), um Produktdetails zu laden.
Der WhereClause kann Platzhalter nutzen, die aus der aktuellen Ergebniszeile ersetzt werden.
Beispiel-Idee: ProductId = '{ProductId}'
Experteneinstellungen
Trainingsdaten speichern
Wenn aktiv, werden Trainings-Samples in model{ID}_sampleslog gespeichert.
Dient Analysezwecken.
Kandidaten speichern
Wenn aktiv, werden Kandidaten pro Vorhersage in model{ID}_candidateslog gespeichert.
Dient Analysezwecken.
Nachverfolgen
Hier können mehrere Syncs ausgewählt werden, die über das Smart-Selling-Widget adhoc durch den Benutzer zu bestimmten Vorhersagen gestartet werden können.
Für eine einfache Konfiguration steht ein Konnektor für Modelle zur Verfügung, der Schemaobjekte je Modelltyp erzeugt. Hier können Syncs konfiguriert werden, die entweder mit einzelnen Vorhersagen oder einer geschachtelten Liste von Vorhersagen ausgeführt werden.
Datenhaltung
Beim ersten Lauf werden folgende Tabellen in der Support-DB erzeugt:
Tabellen
model{ID}_sourcedata
Zwischenspeicher der Quelldaten (Käufe/Belege)model{ID}_modeldata
Enthält:model_data: serialisiertes Modellmodel_metrics: Evaluationsmetriken (JSON)model_assoc_json: Hilfsdaten (Assoc + PopularPool + Produkt-Mappings) als JSON
model{ID}_sampleslog(nur Log, optional)
Trainings-Samples (Featurewerte + Label)model{ID}_candidateslog(nur Log, optional)
Kandidatenliste pro CustomerIdmodel{ID}_predictions(Log + Cache, optional)
gespeicherte Vorhersagen pro CustomerId
Views (Aggregationen)
vmodel{ID}_ProductPopularity
Produktpopularität (ProductId, Family, Count)vmodel{ID}_CustomerFamilyFeatures
Familien-Käufe je Kunde (CustomerId, Family, Count)vmodel{ID}_ProductsDistinct
Distinct ProductId → Family
Ablauf: Training
Das Training wird ausgeführt, wenn der Starttyp nicht AdHoc ist (manuell oder zeitgesteuert).
1) Quelldaten vorbereiten
- Wenn
model{ID}_sourcedatanicht existiert:- Tabellen + Views erzeugen
- Quelldaten importieren
- Sonst:
- Schema ggf. erweitern
- Views neu erzeugen
- optional Update (
UpdateSourceDataOnExecute)
2) Trainingsdaten bauen
Positivbeispiele:
- Laden von Käufen
- optionaler Zeitfilter über letzte x Tage
- Begrenzung über maximale Anzahl
Feature-Aggregate:
CustomerFamilyCounts: Familienkäufe je Kunde (nur Kunden aus den Positives)ProductFamilyById: Produkt → FamilieProductsByFamily: Familie → Liste ProdukteBoughtProductsByCustomer: Kunde → Set gekaufter ProduktePopularSampler: gewichtete Ziehung aus PopularPool
Negativbeispiele pro Positivem:
- abhängig von Verfahren
Assoziierte Produktfamilien: ziehe erst über Assoziationen (Land → Assoc, sonst global)- sonst / Fallback: ziehe über Popularität
- Negatives werden nur akzeptiert, wenn das Produkt nicht in den Käufen des Kunden ist.
3) Optional: Logging
- Trainingsdaten in
model{ID}_sampleslog
4) Modelltraining (LightGBM)
Pipeline:
- OneHotEncoding für CustomerId/Industry/Country/ProductId/Family
- Convert bool/float Features
- Feature Concatenate
- LightGBM Binary Classification (Iterations 200, LR 0.05, Leaves 64, MinExamplesPerLeaf 20)
5) Testsplit & Metriken
- Stratified Split: 20% der Positives und 20% der Negatives als Test
- Evaluate:
AreaUnderRocCurvewird in der UI als Kennzahl ausgegeben (gerundet)
Hinweis zur Interpretation:
Der Split ist sample-basiert. CustomerIds/Products können in Train und Test vorkommen. Das kann Evaluations-Metriken deutlich “optimistischer” machen als ein echter Online-Betrieb.
6) Speichern
- Modell wird serialisiert und in
model{ID}_modeldata.model_datagespeichert - Metriken als JSON in
model_metrics - Hilfsdaten (Assoc/PopularPool/Mappings) als JSON in
model_assoc_json
Zusätzlich werden beim Training alte Vorhersagen/Kandidaten gelöscht:
TRUNCATE model{ID}_predictionsTRUNCATE model{ID}_candidateslog
Ablauf: Vorhersage / Empfehlung
Vorhersage kann auf zwei Arten passieren:
- AdHoc-Start:
- erwartet Parameter
CustomerId - setzt intern
SavePredictions = true - ruft
Recommend(customerId, MaxPredictions)auf
- erwartet Parameter
- Datenabruf über Widget
- kann gespeicherte Vorhersagen verwenden (
SavePredictions) - erzeugt ansonsten neue Vorhersagen via
Recommend
- kann gespeicherte Vorhersagen verwenden (
1) Modell + Hilfsdaten laden
LoadModelBundle()lädt Modell und Hilfsdaten (aux JSON) ausmodeldata- Falls Hilfsdaten fehlen: Fallback lädt PopularPool + Mappings aus Views
2) Kundenprofil laden
LoadCustomerProfileForRecommend(customerId):- liest bis zu 20.000 Käufe des Kunden
- setzt Industry/Country aus erster Zeile
- baut Sets:
BoughtProductsBoughtFamilies
- Zusätzlich:
LoadCustomerFamilyCountsForCustomer(customerId)lädt Familienkaufzähler für Feature-Berechnung.
3) Kandidatenliste erzeugen
Ziel: Liste möglicher Produkte, die bewertet werden.
maxCandidates = max(500, maxRecommendations * 120)
3a) Kandidaten über assoziierte Familien (nur wenn NegativesType = AssociatedFamilies)
- Bestimme AssocModel: zuerst land-spezifisch, sonst global
- Für gekaufte Familien (FamilyA) werden assoziierte Familien (FamilyB) gesammelt
- Pro FamilyB werden zufällig Produkte gezogen (
perFamilyBLimit = 12) - Bereits gekaufte Produkte werden ausgeschlossen
3b) Auffüllen über Popularität
- Populäre Produkte werden hinzugefügt, bis maxCandidates erreicht ist
- Bereits gekaufte Produkte werden ausgeschlossen
Optional: LogCandidateData speichert Kandidaten in model{ID}_candidateslog.
4) Scoring (ML-Scoring pro Kandidat)
Für jeden Kandidaten wird ein RecommendationSample aufgebaut und via PredictionEngine bewertet.
Es wird die Probability verwendet.
Interpretation Probability
- Probability ist die kalibrierte Ausgabe des Binary-Classifiers für die “positive Klasse” (Label = gekauft).
- Aufgrund synthetischer Negatives ist sie keine echte Kaufwahrscheinlichkeit, sondern ein Ranking-Score zur Sortierung der Kandidaten.
5) Erklärung (Explanation)
Wenn NegativesType = AssociatedFamilies und Assoc-Daten verfügbar sind:
- Es wird eine Begründung über die beste passende Familien-Assoziation erzeugt:
- „Kunden, die Familie A kaufen, kaufen häufig auch Familie B …“
Wenn keine passende Assoziation gefunden wird oder PopularOnly:
- Erklärung basiert auf Score bzw. Popularität.
6) Ergebnis & Speichern
- Top-N nach Probability
- Probability wird gerundet:
Math.Round(x.Prob, 2) - Wenn
SavePredictionsaktiv:- Ergebnisse werden in
model{ID}_predictionsgeschrieben (Cache + Log)
- Ergebnisse werden in
Ausgabe / Ergebnis-Spalten
Standardmäßig werden ausgegeben:
ProductIdProductFamilyProbabilityExplanation
Zusätzliche Spalten können über eine eigene Seite ausgewählt werden.
Wenn die Produktsuche gesetzt wurde, werden Produktstammdaten je Ergebniszeile zusätzlich nachgeladen und angehängt.
Tipps & Hinweise
Performance
- Kandidatenanzahl (
maxCandidates) ist ein zentraler Hebel für Vorhersage-Laufzeit.
Qualität / Metriken
- Offline-Metriken können zu optimistisch sein, da CustomerId/ProductId in Train und Test vorkommen.
Reset
Über die Oberfläche können Views und Tabellen gelöscht werden:
- Views:
vmodel{ID}_ProductPopularity,vmodel{ID}_CustomerFamilyFeatures,vmodel{ID}_ProductsDistinct - Tabellen:
model{ID}_sourcedata,model{ID}_modeldata,model{ID}_sampleslog,model{ID}_candidateslog,model{ID}_predictions
Damit wird ein kompletter Neuaufbau (Import + Training) erzwungen.
Einrichtung
Folgender Ablauf richtet Ihr Modell ein und führt das Training aus.
- Wechseln Sie in den Bereich KI
- Klicken Sie auf Neu / Modell und wählen Sie den Typ Produktempfehlung aus.
- Definieren Sie einen Konnektor für das Abrufen der Käufe (positive Beispiele). Der Konnektor muss Abfragen unterstützen.
- Wechseln Sie in den Bereich Features auswählen.
- Definieren Sie die Abfragen. Mit der Verwendung von Platzhaltern können Sie eine kontinuierliche Übertragung von neuen Verkaufsdaten erreichen. Hierfür sollten die relevanten Felder in der Kategorie Quelldaten. festgelegt werden.
- Die Abfrage sollte auch verfälschende Verkäufe, wie Versandkosten, ausschließen.
- Nachdem Sie das Schema abgerufen haben, ordnen Sie den Feldern eine Bedeutung zu.
- Als letzten Schritt kann noch die Darstellung im SmartSelling Widget angepasst werden.
- Mit einer manuellen oder zeitgesteuerten Ausführung werden die Quelldaten geladen und das Modell trainiert.
- Mit dem Widget oder einer Adhoc-Ausführung wird eine Vorhersage berechnet.
Interpretation der Ergebnisse
Die ROC-Kurve misst die Trennschärfe / Ranking-Fähigkeit des Modells.
- 0,5 : Zufall
- 0,7-0,8 : brauchbar
- 0,8-0,9 : gut
- > 0,9 : sehr gut
Beispiel: Fläche unter der ROC-Kurce = 0,9915
Wenn du zufällig ein positives (gekauft) und ein negatives (nicht gekauft) Beispiel nimmst, dann ordnet das Modell das positive in ~99,15% der Fälle höher ein als das negative.
Die Wahrscheinlichkeit ist keine echte Kaufwahrscheinlichkeit, da die Negativbeispiele synthetisch hergestellt werden. Die Aussage ist dadurch eher:
Wie stark glaubt das Modell, dass der Kandidat im Training ein Positivbeispiel gewesen wäre.
Für Empfehlungen zählt meistens die Sortierung (Top N) und nicht die absolute Zahl.
Was kann man aus einer maximalen Wahrscheinlichkeit von 84% konkret ableiten?
- Wenn innerhalb eines Kunden die Top-Produkte z.B. 0,84, 0,62, 0,41… haben, ist das ein gutes Zeichen: das Modell hat Konfidenz-Unterschiede.
- Wenn fast alle Kandidaten nur 0,01–0,05 haben und Top ist 0,06, dann ist das Modell zwar evtl. gut im Ranking, aber insgesamt “unsicher” → oft ein Kandidaten-Thema.
- 84% als Maximum bedeutet schlicht: “Das Modell ist bei den besten Kandidaten ziemlich überzeugt, aber nicht ‘100% sicher’.” Das ist in Empfehlungssystemen üblich und ein normaler bis guter Wert.
- Das Modell kann aus plausiblen Kandidaten (assoziierte Familien) konsistent die besseren nach oben sortieren.
Wie beurteilt man, ob das wirklich gut ist?
Für Empfehlungsmodelle ist der bessere Realitätscheck die Verteilung in den Top N Empfehlungen.
Wenn man häufig sowas siehst:
- Top 1 ~ 0.84
- Top 20 ~ 0.20–0.40
Modell hat klaren “Spread” und kann gut ranken.
Wenn eher:
- Top 1 ~ 0.10
- Top 20 ~ 0.06
Kandidaten sind für den Kunden kaum unterscheidbar oder Features fehlen.