lindritdev commited on
Commit
fb2c62e
·
verified ·
1 Parent(s): 40394e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -127
app.py CHANGED
@@ -1,139 +1,92 @@
 
 
1
  import gradio as gr
2
- import tensorflow as tf
3
- import numpy as np
4
  import pandas as pd
 
 
 
 
 
 
5
 
6
- model_path = "kia_apartment_keras_model.keras"
7
- model = tf.keras.models.load_model(model_path)
8
 
9
- df_bfs_data = pd.read_csv('bfs_municipality_and_tax_data.csv', sep=',', encoding='utf-8')
10
- df_bfs_data['tax_income'] = df_bfs_data['tax_income'].str.replace("'", "").astype(float)
 
 
 
 
11
 
12
- locations = {
13
- "Zürich": 261,
14
- "Kloten": 62,
15
- "Uster": 198,
16
- "Illnau-Effretikon": 296,
17
- "Feuerthalen": 27,
18
- "Pfäffikon": 177,
19
- "Ottenbach": 11,
20
- "Dübendorf": 191,
21
- "Richterswil": 138,
22
- "Maur": 195,
23
- "Embrach": 56,
24
- "Bülach": 53,
25
- "Winterthur": 230,
26
- "Oetwil am See": 157,
27
- "Russikon": 178,
28
- "Obfelden": 10,
29
- "Wald (ZH)": 120,
30
- "Niederweningen": 91,
31
- "Dällikon": 84,
32
- "Buchs (ZH)": 83,
33
- "Rüti (ZH)": 118,
34
- "Hittnau": 173,
35
- "Bassersdorf": 52,
36
- "Glattfelden": 58,
37
- "Opfikon": 66,
38
- "Hinwil": 117,
39
- "Regensberg": 95,
40
- "Langnau am Albis": 136,
41
- "Dietikon": 243,
42
- "Erlenbach (ZH)": 151,
43
- "Kappel am Albis": 6,
44
- "Stäfa": 158,
45
- "Zell (ZH)": 231,
46
- "Turbenthal": 228,
47
- "Oberglatt": 92,
48
- "Winkel": 72,
49
- "Volketswil": 199,
50
- "Kilchberg (ZH)": 135,
51
- "Wetzikon (ZH)": 121,
52
- "Zumikon": 160,
53
- "Weisslingen": 180,
54
- "Elsau": 219,
55
- "Hettlingen": 221,
56
- "Rüschlikon": 139,
57
- "Stallikon": 13,
58
- "Dielsdorf": 86,
59
- "Wallisellen": 69,
60
- "Dietlikon": 54,
61
- "Meilen": 156,
62
- "Wangen-Brüttisellen": 200,
63
- "Flaach": 28,
64
- "Regensdorf": 96,
65
- "Niederhasli": 90,
66
- "Bauma": 297,
67
- "Aesch (ZH)": 241,
68
- "Schlieren": 247,
69
- "Dürnten": 113,
70
- "Unterengstringen": 249,
71
- "Gossau (ZH)": 115,
72
- "Oberengstringen": 245,
73
- "Schleinikon": 98,
74
- "Aeugst am Albis": 1,
75
- "Rheinau": 38,
76
- "Höri": 60,
77
- "Rickenbach (ZH)": 225,
78
- "Rafz": 67,
79
- "Adliswil": 131,
80
- "Zollikon": 161,
81
- "Urdorf": 250,
82
- "Hombrechtikon": 153,
83
- "Birmensdorf (ZH)": 242,
84
- "Fehraltorf": 172,
85
- "Weiach": 102,
86
- "Männedorf": 155,
87
- "Küsnacht (ZH)": 154,
88
- "Hausen am Albis": 4,
89
- "Hochfelden": 59,
90
- "Fällanden": 193,
91
- "Greifensee": 194,
92
- "Mönchaltorf": 196,
93
- "Dägerlen": 214,
94
- "Thalheim an der Thur": 39,
95
- "Uetikon am See": 159,
96
- "Seuzach": 227,
97
- "Uitikon": 248,
98
- "Affoltern am Albis": 2,
99
- "Geroldswil": 244,
100
- "Niederglatt": 89,
101
- "Thalwil": 141,
102
- "Rorbas": 68,
103
- "Pfungen": 224,
104
- "Weiningen (ZH)": 251,
105
- "Bubikon": 112,
106
- "Neftenbach": 223,
107
- "Mettmenstetten": 9,
108
- "Otelfingen": 94,
109
- "Flurlingen": 29,
110
- "Stadel": 100,
111
- "Grüningen": 116,
112
- "Henggart": 31,
113
- "Dachsen": 25,
114
- "Bonstetten": 3,
115
- "Bachenbülach": 51,
116
- "Horgen": 295
117
- }
118
 
119
- # Define the core prediction function
120
- def predict_apartment(rooms, area, town):
121
- bfs_number = locations[town]
122
- df = df_bfs_data[df_bfs_data['bfs_number']==bfs_number]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- if len(df) != 1: # if there are more than two records with the same bfs_number reutrn -1
125
- return -1
126
 
127
- input = np.array([rooms, area, df['pop'].iloc[0], df['pop_dens'].iloc[0], df['frg_pct'].iloc[0], df['emp'].iloc[0], df['tax_income'].iloc[0]])
128
- input = input.reshape(1, 7)
129
- prediction = model.predict(input)
130
- return np.round(prediction[0][0], 0)
131
 
132
- # Create the Gradio interface
133
  iface = gr.Interface(
134
- fn=predict_apartment,
135
- inputs=["number", "number", gr.Dropdown(choices=locations.keys(), label="Town", type="value")],
136
- outputs=gr.Number()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  )
138
 
139
- iface.launch()
 
 
1
+ # app.py
2
+
3
  import gradio as gr
4
+ import joblib
5
+ import json
6
  import pandas as pd
7
+ import numpy as np
8
+
9
+ # --- 1. Modell & Metadaten laden ---
10
+ # Passe den Pfad an, falls nötig
11
+ MODEL_PATH = "model.pkl" # oder "random_forest_model.joblib"
12
+ FEATURES_PATH = "features.json"
13
 
14
+ model = joblib.load(MODEL_PATH)
15
+ features = json.load(open(FEATURES_PATH, "r"))
16
 
17
+ # Extrahiere die Modell-Kürzel aus den Feature-Namen
18
+ model_dummies = [
19
+ feat.replace("Model_group_", "")
20
+ for feat in features
21
+ if feat.startswith("Model_group_")
22
+ ]
23
 
24
+ # Median-PS zum Auffüllen, falls notwendig
25
+ # Hier setzen wir als Default das Median-PS aus Trainingsdaten;
26
+ # Du kannst hier auch einen festen Wert angeben
27
+ med_ps = np.median([ # Beispiel: ersetze durch echten Median
28
+ # Du kannst das eigentlich in deinem Notebook ausrechnen und hier fest eintragen
29
+ 300, # Platzhalter
30
+ ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ # --- 2. Vorhersage-Funktion ---
33
+ def predict_price(model_main: str, kilometer: float, ps: float, year: int):
34
+ # 2.1 Basis-Input-Vector erstellen
35
+ x = dict.fromkeys(features, 0.0)
36
+ x['Kilometer'] = float(kilometer)
37
+ x['PS'] = float(ps)
38
+ x['month'] = 1 # Standard-Januar; nur für Alter nötig
39
+ x['year'] = int(year)
40
+
41
+ # Alter berechnen
42
+ today = pd.Timestamp('2025-05-24')
43
+ dt = pd.Timestamp(year=year, month=1, day=1)
44
+ age_days = (today - dt).days
45
+ x['age_days'] = float(age_days)
46
+ x['age_years'] = float(age_days) / 365.0
47
+
48
+ # Getriebe: per Default Automatik (gear_Schaltgetriebe = 0)
49
+ # Wenn du willst, kannst du hier noch ein Dropdown für Getriebe hinzufügen
50
+
51
+ # 2.2 Modell-Dummy setzen
52
+ key = f"Model_group_{model_main}"
53
+ if key in x:
54
+ x[key] = 1.0
55
+ else:
56
+ x['Model_group_Other'] = 1.0
57
 
58
+ # 2.3 DataFrame bauen
59
+ df_input = pd.DataFrame([x], columns=features)
60
 
61
+ # 2.4 Vorhersage
62
+ pred = model.predict(df_input)[0]
63
+ return round(float(pred), 2)
 
64
 
65
+ # --- 3. Gradio-Interface ---
66
  iface = gr.Interface(
67
+ fn=predict_price,
68
+ inputs=[
69
+ gr.Dropdown(
70
+ choices=sorted(model_dummies),
71
+ label="BMW Modell-Kürzel",
72
+ value=model_dummies[0]
73
+ ),
74
+ gr.Number(label="Kilometer", value=50000),
75
+ gr.Number(label="PS", value=med_ps),
76
+ gr.Number(label="Baujahr", value=2020, precision=0)
77
+ ],
78
+ outputs=gr.Number(label="Geschätzter Preis (CHF)"),
79
+ title="BMW Price Predictor",
80
+ description=(
81
+ "Wähle das BMW-Kürzel (z.B. M3, X5, 120i), gib Kilometer, PS und Baujahr ein – "
82
+ "und erhalte eine geschätzte Preisprognose in CHF."
83
+ ),
84
+ examples=[
85
+ ["M3", 20000, 450, 2021],
86
+ ["X5", 50000, 300, 2019],
87
+ ["M4", 10000, 480, 2023],
88
+ ]
89
  )
90
 
91
+ if __name__ == "__main__":
92
+ iface.launch()