mimo1972 commited on
Commit
cf0cab6
·
verified ·
1 Parent(s): 39376cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -74
app.py CHANGED
@@ -1,74 +1,120 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import joblib
4
-
5
- # Konfiguration der Seite
6
- st.set_page_config(page_title="Customer Cluster Predictor", layout="centered")
7
-
8
- # Ressourcen laden
9
- @st.cache_resource
10
- def load_resources():
11
- # Laden des Modells aus Ihrer Datei kmeans_model.pkl [cite: 3, 4]
12
- model = joblib.load('kmeans_model.pkl')
13
- return model
14
-
15
- model = load_resources()
16
-
17
- # Definition der Cluster-Namen und Marketing-Strategien basierend auf der Analyse
18
- cluster_info = {
19
- 0: {
20
- "Name": "Inaktive Kleinnutzer",
21
- "Beschreibung": "Niedrige Einlösewerte und sehr lange inaktiv.",
22
- "Strategie": "Reaktivierungskampagne: Senden Sie einen attraktiven Willkommens-Gutschein."
23
- },
24
- 1: {
25
- "Name": "Regelmäßige Gelegenheitsnutzer",
26
- "Beschreibung": "Moderate Werte, regelmäßig aktiv.",
27
- "Strategie": "Kundenbindung: Bieten Sie kleine Belohnungen für die nächste Einlösung an."
28
- },
29
- 2: {
30
- "Name": "VIP-Kunden (Top-Segment)",
31
- "Beschreibung": "Höchste Werte, sehr hohe Punktzahl und sehr aktiv.",
32
- "Strategie": "Exklusivität: Einladungen zu VIP-Events oder exklusive Angebote."
33
- },
34
- 3: {
35
- "Name": "Treue Bestandskunden",
36
- "Beschreibung": "Hohe Werte und konstante Aktivität.",
37
- "Strategie": "Upselling: Empfehlen Sie höherwertige Prämien-Kategorien."
38
- },
39
- 4: {
40
- "Name": "Gefährdete Kunden (At-Risk)",
41
- "Beschreibung": "Moderate Werte, aber die letzte Einlösung liegt lange zurück.",
42
- "Strategie": "Dringlichkeit: Senden Sie eine 'Wir vermissen Sie'-Aktion mit Bonus."
43
- }
44
- }
45
-
46
- st.title("👤 Strategische Kunden-Segmentierung")
47
- st.markdown("Ermitteln Sie das Segment und die passende Marketing-Strategie.")
48
-
49
- # Eingabefelder für die 2 vom Nutzer geforderten Werte
50
- latest_days = st.number_input("Tage seit letzter Einlösung (latest_redeem_days)", min_value=0, value=1)
51
- redeem_value = st.number_input("Einlösewert (total_redeem_value)", min_value=0.0, value=1.0)
52
-
53
- # Automatische Berechnung der Punkte (Wert * 10)
54
- redeem_points = redeem_value * 10
55
- st.write(f"Berechnete Punkte: **{redeem_points}**")
56
-
57
- # Verarbeitung
58
- if st.button("Cluster berechnen"):
59
- try:
60
- # Vorbereitung der Rohdaten (Reihenfolge wie im Training: Value, Points, Days)
61
- input_data = [[float(redeem_value), float(redeem_points), float(latest_days)]]
62
-
63
- # Vorhersage ohne Scaler (da das Modell auf Rohdaten trainiert wurde)
64
- cluster_pred = model.predict(input_data)[0]
65
- info = cluster_info[cluster_pred]
66
-
67
- # Ergebnis-Anzeige
68
- st.divider()
69
- st.header(f"Ergebnis: {info['Name']} (Cluster {cluster_pred})")
70
- st.write(f"**Profil:** {info['Beschreibung']}")
71
- st.success(f"💡 **Marketing-Strategie:** {info['Strategie']}")
72
-
73
- except Exception as e:
74
- st.error(f"Fehler bei der Vorhersage: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st # Import steht ganz oben
2
+ import pandas as pd
3
+ import joblib
4
+ import matplotlib.pyplot as plt
5
+ import seaborn as sns
6
+ from sklearn.decomposition import PCA
7
+
8
+ # 1. Seite konfigurieren
9
+ st.set_page_config(page_title="Customer Segment Analysis", layout="wide")
10
+
11
+ # 2. Ressourcen laden & Reinigung (exakt wie in Ihrem Notebook)
12
+ @st.cache_resource
13
+ def load_and_clean_data():
14
+ model = joblib.load('kmeans_model.pkl')
15
+ try:
16
+ df = pd.read_parquet('featrures.parquet')
17
+ # Tippfehler-Korrektur
18
+ df.rename(columns={'latest_redeem_dayes': 'latest_redeem_days'}, inplace=True)
19
+
20
+ # IQR Reinigung laut Notebook Cell 17
21
+ cols = ['total_redeem_value', 'total_redeem_points', 'latest_redeem_days']
22
+ Q1, Q3 = df[cols].quantile(0.25), df[cols].quantile(0.75)
23
+ IQR = Q3 - Q1
24
+ df_cleaned = df[~((df[cols] < (Q1 - 1.5 * IQR)) | (df[cols] > (Q3 + 1.5 * IQR))).any(axis=1)].copy()
25
+
26
+ # Duplikate entfernen laut Cell 20
27
+ df_final = df_cleaned.drop_duplicates().reset_index(drop=True)
28
+ return model, df_final
29
+ except:
30
+ return model, pd.DataFrame()
31
+
32
+ model, features = load_and_clean_data()
33
+
34
+ # Cluster-Definitionen
35
+ cluster_info = {
36
+ 0: {"Name": "Inaktive Kleinnutzer", "Strategie": "Reaktivierung: Gutschein senden."},
37
+ 1: {"Name": "Regelmäßige Gelegenheitsnutzer", "Strategie": "Treue-Bonus anbieten."},
38
+ 2: {"Name": "VIP-Kunden (Top-Segment)", "Strategie": "Exklusive VIP-Events."},
39
+ 3: {"Name": "Treue Bestandskunden", "Strategie": "Upselling-Angebote."},
40
+ 4: {"Name": "Gefährdete Kunden", "Strategie": "Dringlichkeits-Aktion."}
41
+ }
42
+
43
+ st.title("👤 Kunden-Segmentierung & Visualisierung")
44
+
45
+ col1, col2 = st.columns([1, 2])
46
+
47
+ with col1:
48
+ st.header("Eingabe")
49
+
50
+ # NEU: Maximale Grenzwerte gesetzt
51
+ latest_days = st.number_input(
52
+ "Tage seit letzter Einlösung",
53
+ min_value=0,
54
+ max_value=590, # Limit auf 590 Tage
55
+ value=50
56
+ )
57
+
58
+ redeem_value = st.number_input(
59
+ "Einlösewert (Value)",
60
+ min_value=0.0,
61
+ max_value=950.0, # Limit auf 950
62
+ value=200.0
63
+ )
64
+
65
+ # Punkte-Berechnung
66
+ redeem_points = redeem_value * 10
67
+ st.info(f"Berechnete Punkte: **{redeem_points}**")
68
+
69
+ if st.button("Analyse starten"):
70
+ input_data = [[float(redeem_value), float(redeem_points), float(latest_days)]]
71
+ prediction = model.predict(input_data)[0]
72
+ st.session_state['pred'] = prediction
73
+ st.session_state['input'] = input_data
74
+
75
+ # 3. Ergebnis & Grafik-Logik
76
+ if 'pred' in st.session_state:
77
+ prediction = st.session_state['pred']
78
+ info = cluster_info[prediction]
79
+
80
+ with col2:
81
+ st.subheader(f"Ergebnis: {info['Name']} (Cluster {prediction})")
82
+ st.success(f"💡 **Marketing-Strategie:** {info['Strategie']}")
83
+
84
+ if not features.empty:
85
+ st.divider()
86
+ with st.spinner("Grafik wird generiert..."):
87
+ cols = ['total_redeem_value', 'total_redeem_points', 'latest_redeem_days']
88
+ X = features[cols]
89
+
90
+ # PCA Logik wie im Notebook
91
+ pca = PCA(n_components=2)
92
+ pca_data = pca.fit_transform(X)
93
+
94
+ # Neuen Punkt transformieren
95
+ new_point_pca = pca.transform(pd.DataFrame(st.session_state['input'], columns=cols))
96
+
97
+ # Plotting
98
+ fig, ax = plt.subplots(figsize=(10, 7))
99
+ sns.scatterplot(
100
+ x=pca_data[:, 0], y=pca_data[:, 1],
101
+ hue=model.predict(X),
102
+ palette='tab10', alpha=0.5, s=60, ax=ax
103
+ )
104
+
105
+ # Das rote X für den neuen Kunden
106
+ ax.scatter(
107
+ new_point_pca[0, 0], new_point_pca[0, 1],
108
+ c='red', marker='X', s=350,
109
+ label='Dieser Kunde', edgecolor='black', zorder=15
110
+ )
111
+
112
+ # Dynamische Achsenanpassung für Sichtbarkeit
113
+ all_x = list(pca_data[:, 0]) + [new_point_pca[0, 0]]
114
+ all_y = list(pca_data[:, 1]) + [new_point_pca[0, 1]]
115
+ ax.set_xlim(min(all_x) - 50, max(all_x) + 50)
116
+ ax.set_ylim(min(all_y) - 50, max(all_y) + 50)
117
+
118
+ ax.set_title("Kundenposition im Vergleich zu den Clustern")
119
+ ax.legend(title="Cluster-ID", bbox_to_anchor=(1.05, 1), loc='upper left')
120
+ st.pyplot(fig)