Marcel0123 commited on
Commit
03df781
·
verified ·
1 Parent(s): c2933ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -75
app.py CHANGED
@@ -1,4 +1,5 @@
1
- # app.py — Titanic Data Adventure (fix: stabiele 2D-plot + lange intro)
 
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
@@ -11,12 +12,10 @@ from sklearn.compose import ColumnTransformer
11
  from sklearn.pipeline import Pipeline
12
  from sklearn.ensemble import RandomForestClassifier
13
  from sklearn.decomposition import PCA
14
- try:
15
- from sklearn.manifold import TSNE
16
- HAS_TSNE = True
17
- except Exception:
18
- HAS_TSNE = False
19
 
 
 
 
20
  REQUIRED = {"survived","pclass","sex","age","sibsp","parch","fare","embarked"}
21
 
22
  def load_data(path="Titanic-Dataset.csv"):
@@ -24,9 +23,9 @@ def load_data(path="Titanic-Dataset.csv"):
24
  raise FileNotFoundError("❌ Titanic-Dataset.csv niet gevonden in de rootmap.")
25
  df = pd.read_csv(path)
26
  df.columns = [c.lower().strip() for c in df.columns]
27
- miss = REQUIRED - set(df.columns)
28
- if miss:
29
- raise ValueError(f"Ontbrekende kolommen: {', '.join(sorted(miss))}")
30
  for c in df.columns:
31
  if df[c].isna().any():
32
  df[c] = df[c].fillna(df[c].mode()[0] if df[c].dtype=='O' else df[c].median())
@@ -40,36 +39,15 @@ df = load_data()
40
  MODEL = None
41
  MODEL_ACC = None
42
 
 
 
 
43
  def hero_path():
44
  for n in ["titanic_bg.png","titanic_bg.jpg","titanic_bg.jpeg"]:
45
- if os.path.exists(n): return n
 
46
  return None
47
 
48
- INTRO_MD = """
49
- # 🛳️ Titanic Data Adventure
50
- ### Een datagedreven reis door hoop, hiërarchie en toeval
51
-
52
- **April 1912.**
53
- De RMS *Titanic* vertrekt richting New York: een drijvend paleis, gevuld met verwachtingen. Aan boord: industriëlen in avondkleding, jonge gezinnen met één koffer, bemanningsleden die elke dag routine tot ritueel verheffen. De zee is kalm; de toekomst lijkt maakbaar.
54
-
55
- Meer dan een eeuw later kijken wij mee — niet met verrekijkers of logboeken, maar met **data**. Elk record in deze dataset is een menselijk verhaal: iemand met een plek aan tafel, een ticket, een familie, een keuze. Door de gegevens te verkennen, begrijpen we beter **wie overleefde — en waarom**.
56
-
57
- ---
58
-
59
- ## Wat je in dit dashboard gaat zien
60
- - **2D-Passagierskaart** — elk bolletje is één passagier. We projecteren alle kenmerken naar 2 dimensies (PCA; t-SNE indien beschikbaar).
61
- Beweeg met je muis over de punten voor **details** (klasse, leeftijd, geslacht, familie, prijs, enz.).
62
- - **Leeftijdsverdeling**, **Geslachtsverdeling**, **Fare per klasse**.
63
- - **Jouw scenario** — stel je kenmerken in, bereken je kans en lees een korte scène uit die nacht.
64
-
65
- ---
66
-
67
- ## Wat een model wél en niet doet
68
- - ✅ Herkent patronen (*geslacht + klasse + leeftijd*).
69
- - ✅ Geeft **kansen**, geen zekerheden.
70
- - ❌ Velt geen moreel oordeel; context buiten de data blijft onzichtbaar.
71
- """
72
-
73
  def make_plot(fig, title):
74
  fig.update_layout(
75
  title=title,
@@ -82,43 +60,43 @@ def make_plot(fig, title):
82
  )
83
  return fig
84
 
85
- def train_and_embed(progress=gr.Progress(track_tqdm=True)):
 
 
 
 
 
 
 
 
86
  global MODEL, MODEL_ACC
87
- progress(0.05, desc="📦 Data laden…")
88
- status = f"📦 Data geladen: **{len(df)}** passagiers."
89
- yield status, make_plot(px.scatter(x=[], y=[]), "Initialiseren…")
90
 
91
- # Voorbewerking + model
92
- feats = ["pclass","sex","age","sibsp","parch","fare","embarked","family_size"]
93
- X = df[feats].copy()
94
  y = df["survived"].astype(int)
95
- cat = ["sex","embarked"]; num = [c for c in feats if c not in cat]
 
 
 
96
  pre = ColumnTransformer([
97
- ("num", StandardScaler(), num),
98
- ("cat", OneHotEncoder(handle_unknown="ignore"), cat)
 
 
 
 
 
99
  ])
100
- progress(0.35, desc="🤖 Model trainen…")
101
- pipe = Pipeline([("prep", pre), ("clf", RandomForestClassifier(n_estimators=300, random_state=42))])
102
  Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
103
  pipe.fit(Xtr, ytr)
104
- MODEL = pipe; MODEL_ACC = pipe.score(Xte, yte)
105
- status = f"✅ Model getraind (RandomForest), nauwkeurigheid: **{MODEL_ACC:.2%}**."
106
- yield status, make_plot(px.scatter(x=[], y=[]), "Model klaar — projectie opbouwen…")
107
 
108
- # Embedding: stabiel met PCA, optioneel TSNE erop
109
- progress(0.65, desc="🗺️ 2D-projectie (PCA)…")
110
  Z = pre.fit_transform(X)
111
  Z = Z.toarray() if hasattr(Z, "toarray") else Z
112
  emb = PCA(n_components=2, random_state=42).fit_transform(Z)
113
- method = "PCA"
114
- if HAS_TSNE:
115
- try:
116
- progress(0.85, desc="✨ t-SNE verfijning…")
117
- emb = TSNE(n_components=2, perplexity=30, learning_rate="auto", init="pca",
118
- n_iter=600, random_state=42).fit_transform(Z)
119
- method = "t-SNE"
120
- except Exception:
121
- pass
122
 
123
  dvis = pd.DataFrame({"x": emb[:,0], "y": emb[:,1]})
124
  dvis["Overleving"] = df["status"].values
@@ -128,22 +106,25 @@ def train_and_embed(progress=gr.Progress(track_tqdm=True)):
128
  dvis["Fare (£)"] = df["fare"].values
129
  dvis["Familie"] = df["family_size"].values
130
  for c in ["name","ticket","cabin"]:
131
- if c in df.columns: dvis[c.capitalize()] = df[c].values
 
132
 
133
  fig = px.scatter(
134
  dvis, x="x", y="y",
135
  color="Overleving", symbol="Klasse",
136
  hover_data=[col for col in dvis.columns if col not in ["x","y"]],
137
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"},
138
- opacity=0.78
139
  )
140
  fig.update_traces(marker=dict(symbol="circle", size=8, line=dict(width=0.6, color="white")))
141
- fig = make_plot(fig, f"2D-projectie ({method}) — elk bolletje is een passagier")
142
 
143
- progress(1.0, desc="Klaar ")
144
- status = f"✅ Model klaar (**{MODEL_ACC:.2%}**). 2D-projectie ({method}) gereed — hover voor details."
145
- yield status, fig
146
 
 
 
 
147
  def plot_age_hist(dfx):
148
  f = px.histogram(dfx, x="age", color="status", nbins=30, barmode="overlay", opacity=0.75,
149
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
@@ -159,6 +140,9 @@ def plot_fare_box(dfx):
159
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
160
  return make_plot(f, "Ticketprijs per klasse (met overleving)")
161
 
 
 
 
162
  def predict_and_story(pclass, sex, age, sibsp, parch, fare, embarked):
163
  if MODEL is None:
164
  return "⏳ Het model initialiseert nog. Probeer het zo nog eens."
@@ -192,6 +176,40 @@ def predict_and_story(pclass, sex, age, sibsp, parch, fare, embarked):
192
  **Avontuur:** De nacht is stil; fluiten, geroep, voetstappen. {ending}
193
  """
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  CUSTOM_CSS = """
196
  body { background:#FFFFFF; color:#0B1C3F; }
197
  .gradio-container { background:#FFFFFF; }
@@ -215,7 +233,7 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as d
215
 
216
  with gr.Column(elem_classes=["panel"]):
217
  gr.Markdown("## 🔧 Initialisatie & Modeltraining")
218
- status_md = gr.Markdown("⏳ Start…")
219
  train_plot = gr.Plot(label="2D-projectie — elk bolletje is een passagier")
220
 
221
  with gr.Row():
@@ -245,15 +263,12 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as d
245
  btn = gr.Button("🎲 Bereken én vertel mijn verhaal", variant="primary")
246
  story_out = gr.Markdown()
247
 
248
- # streamende training + embedding
249
- demo.load(fn=train_and_embed, inputs=[], outputs=[status_md, train_plot])
250
-
251
- # overige grafieken
252
- demo.load(lambda: (plot_age_hist(df), plot_gender(df), plot_fare_box(df)),
253
- inputs=[], outputs=[g2, g3, g4])
254
-
255
  btn.click(predict_and_story,
256
  inputs=[ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb],
257
  outputs=story_out)
258
 
259
  demo.launch()
 
 
1
+ # app.py — Titanic Data Adventure (stabiele versie met PCA-visualisatie en uitgebreide introductie)
2
+
3
  import gradio as gr
4
  import pandas as pd
5
  import numpy as np
 
12
  from sklearn.pipeline import Pipeline
13
  from sklearn.ensemble import RandomForestClassifier
14
  from sklearn.decomposition import PCA
 
 
 
 
 
15
 
16
+ # ======================================================
17
+ # DATA LADEN
18
+ # ======================================================
19
  REQUIRED = {"survived","pclass","sex","age","sibsp","parch","fare","embarked"}
20
 
21
  def load_data(path="Titanic-Dataset.csv"):
 
23
  raise FileNotFoundError("❌ Titanic-Dataset.csv niet gevonden in de rootmap.")
24
  df = pd.read_csv(path)
25
  df.columns = [c.lower().strip() for c in df.columns]
26
+ missing = REQUIRED - set(df.columns)
27
+ if missing:
28
+ raise ValueError(f"Ontbrekende kolommen: {', '.join(sorted(missing))}")
29
  for c in df.columns:
30
  if df[c].isna().any():
31
  df[c] = df[c].fillna(df[c].mode()[0] if df[c].dtype=='O' else df[c].median())
 
39
  MODEL = None
40
  MODEL_ACC = None
41
 
42
+ # ======================================================
43
+ # HULPFUNCTIES
44
+ # ======================================================
45
  def hero_path():
46
  for n in ["titanic_bg.png","titanic_bg.jpg","titanic_bg.jpeg"]:
47
+ if os.path.exists(n):
48
+ return n
49
  return None
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  def make_plot(fig, title):
52
  fig.update_layout(
53
  title=title,
 
60
  )
61
  return fig
62
 
63
+ # ======================================================
64
+ # MODELTRAINING + 2D VISUALISATIE
65
+ # ======================================================
66
+ def train_and_embed_solid():
67
+ """
68
+ Robuuste initialisatie:
69
+ - traint het model
70
+ - maakt stabiele 2D-projectie (PCA)
71
+ """
72
  global MODEL, MODEL_ACC
 
 
 
73
 
74
+ features = ["pclass","sex","age","sibsp","parch","fare","embarked","family_size"]
75
+ X = df[features].copy()
 
76
  y = df["survived"].astype(int)
77
+
78
+ cat_cols = ["sex","embarked"]
79
+ num_cols = [c for c in features if c not in cat_cols]
80
+
81
  pre = ColumnTransformer([
82
+ ("num", StandardScaler(), num_cols),
83
+ ("cat", OneHotEncoder(handle_unknown="ignore"), cat_cols),
84
+ ])
85
+
86
+ pipe = Pipeline([
87
+ ("prep", pre),
88
+ ("clf", RandomForestClassifier(n_estimators=300, random_state=42))
89
  ])
90
+
 
91
  Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
92
  pipe.fit(Xtr, ytr)
93
+ MODEL = pipe
94
+ MODEL_ACC = pipe.score(Xte, yte)
 
95
 
96
+ # 2D embedding met PCA (altijd stabiel)
 
97
  Z = pre.fit_transform(X)
98
  Z = Z.toarray() if hasattr(Z, "toarray") else Z
99
  emb = PCA(n_components=2, random_state=42).fit_transform(Z)
 
 
 
 
 
 
 
 
 
100
 
101
  dvis = pd.DataFrame({"x": emb[:,0], "y": emb[:,1]})
102
  dvis["Overleving"] = df["status"].values
 
106
  dvis["Fare (£)"] = df["fare"].values
107
  dvis["Familie"] = df["family_size"].values
108
  for c in ["name","ticket","cabin"]:
109
+ if c in df.columns:
110
+ dvis[c.capitalize()] = df[c].values
111
 
112
  fig = px.scatter(
113
  dvis, x="x", y="y",
114
  color="Overleving", symbol="Klasse",
115
  hover_data=[col for col in dvis.columns if col not in ["x","y"]],
116
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"},
117
+ opacity=0.8
118
  )
119
  fig.update_traces(marker=dict(symbol="circle", size=8, line=dict(width=0.6, color="white")))
120
+ fig = make_plot(fig, "2D-projectie (PCA) — elk bolletje is een passagier")
121
 
122
+ status = f" Model getraind (RandomForest) — nauwkeurigheid: **{MODEL_ACC:.2%}**. 2D-projectie gereed; hover voor details."
123
+ return status, fig
 
124
 
125
+ # ======================================================
126
+ # OVERIGE GRAFIEKEN
127
+ # ======================================================
128
  def plot_age_hist(dfx):
129
  f = px.histogram(dfx, x="age", color="status", nbins=30, barmode="overlay", opacity=0.75,
130
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
 
140
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
141
  return make_plot(f, "Ticketprijs per klasse (met overleving)")
142
 
143
+ # ======================================================
144
+ # INTERACTIEVE VOORSPELLING
145
+ # ======================================================
146
  def predict_and_story(pclass, sex, age, sibsp, parch, fare, embarked):
147
  if MODEL is None:
148
  return "⏳ Het model initialiseert nog. Probeer het zo nog eens."
 
176
  **Avontuur:** De nacht is stil; fluiten, geroep, voetstappen. {ending}
177
  """
178
 
179
+ # ======================================================
180
+ # LANGE INTRODUCTIETEKST
181
+ # ======================================================
182
+ INTRO_MD = """
183
+ # 🛳️ Titanic Data Adventure
184
+ ### Een datagedreven reis door hoop, hiërarchie en toeval
185
+
186
+ **April 1912.**
187
+ De RMS *Titanic* vertrekt richting New York: een drijvend paleis, gevuld met verwachtingen.
188
+ Aan boord: industriëlen in avondkleding, jonge gezinnen met één koffer, bemanningsleden met routine.
189
+ De zee is kalm; de toekomst lijkt maakbaar.
190
+
191
+ Meer dan een eeuw later kijken wij mee — niet met verrekijkers of logboeken, maar met **data**.
192
+ Elk record in deze dataset is een menselijk verhaal: iemand met een plek aan tafel, een ticket, een familie, een keuze.
193
+ Door de gegevens te verkennen, begrijpen we beter **wie overleefde — en waarom**.
194
+
195
+ ---
196
+
197
+ ## Wat je in dit dashboard ziet
198
+ - **2D-Passagierskaart** — elk bolletje is één passagier (hover voor details).
199
+ - **Leeftijdsverdeling**, **Geslachtsverdeling**, **Fare per klasse**.
200
+ - **Jouw scenario** — stel je kenmerken in, bereken je kans en lees je scène uit die nacht.
201
+
202
+ ---
203
+
204
+ ## Wat het model wél en niet doet
205
+ - ✅ Herkent patronen (*geslacht + klasse + leeftijd*).
206
+ - ✅ Geeft **kansen**, geen zekerheden.
207
+ - ❌ Kent geen context buiten de data: emotie, paniek, toeval.
208
+ """
209
+
210
+ # ======================================================
211
+ # UI + LAYOUT
212
+ # ======================================================
213
  CUSTOM_CSS = """
214
  body { background:#FFFFFF; color:#0B1C3F; }
215
  .gradio-container { background:#FFFFFF; }
 
233
 
234
  with gr.Column(elem_classes=["panel"]):
235
  gr.Markdown("## 🔧 Initialisatie & Modeltraining")
236
+ status_md = gr.Markdown("⏳ Initialiseren…")
237
  train_plot = gr.Plot(label="2D-projectie — elk bolletje is een passagier")
238
 
239
  with gr.Row():
 
263
  btn = gr.Button("🎲 Bereken én vertel mijn verhaal", variant="primary")
264
  story_out = gr.Markdown()
265
 
266
+ # Laden van data en plots
267
+ demo.load(fn=train_and_embed_solid, inputs=[], outputs=[status_md, train_plot])
268
+ demo.load(lambda: (plot_age_hist(df), plot_gender(df), plot_fare_box(df)), inputs=[], outputs=[g2, g3, g4])
 
 
 
 
269
  btn.click(predict_and_story,
270
  inputs=[ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb],
271
  outputs=story_out)
272
 
273
  demo.launch()
274
+