Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import pickle | |
| import os | |
| # Load model | |
| model_filename = "apartment_rf_model.pkl" | |
| with open(model_filename, mode="rb") as f: | |
| model_data = pickle.load(f) | |
| model = model_data["model"] | |
| features = model_data["features"] | |
| log_target = model_data["log_target"] | |
| DEFAULT_POP_DENS_CITY = 4729.0 | |
| DEFAULT_POP_DENS_OUTSIDE = 1328.0 | |
| DEFAULT_FRG_PCT = 25.0 | |
| DEFAULT_LAT_CITY = 47.380402 | |
| DEFAULT_LON_CITY = 8.530496 | |
| DEFAULT_LAT_OUTSIDE = 47.424900 | |
| DEFAULT_LON_OUTSIDE = 8.638663 | |
| def predict_price( | |
| rooms, area, tax_income, | |
| luxurious, furnished, temporary, zurich_city, | |
| attika, loft, seesicht, | |
| kreis | |
| ): | |
| # Use data-derived defaults for hidden features | |
| pop_dens = DEFAULT_POP_DENS_CITY if zurich_city else DEFAULT_POP_DENS_OUTSIDE | |
| lat = DEFAULT_LAT_CITY if zurich_city else DEFAULT_LAT_OUTSIDE | |
| lon = DEFAULT_LON_CITY if zurich_city else DEFAULT_LON_OUTSIDE | |
| frg_pct = DEFAULT_FRG_PCT | |
| # Derived features | |
| log_area = np.log1p(area) | |
| log_rooms = np.log1p(rooms) | |
| rooms_area_ratio = rooms / (area + 1) | |
| room_per_m2 = area / rooms if rooms > 0 else area | |
| income_density_score = tax_income * pop_dens / 1e6 | |
| log_income_dens = np.log1p(income_density_score) | |
| log_pop_dens = np.log1p(pop_dens) | |
| area_rooms_interact = area * rooms | |
| # Kreis dummies | |
| kreis_cols = {f"Kreis {i}": 0 for i in range(1, 13)} | |
| if kreis in kreis_cols: | |
| kreis_cols[kreis] = 1 | |
| input_dict = { | |
| "rooms": rooms, | |
| "area": area, | |
| "log_area": log_area, | |
| "log_rooms": log_rooms, | |
| "pop_dens": pop_dens, | |
| "log_pop_dens": log_pop_dens, | |
| "frg_pct": frg_pct, | |
| "tax_income": tax_income, | |
| "income_density_score": income_density_score, | |
| "log_income_dens": log_income_dens, | |
| "rooms_area_ratio": rooms_area_ratio, | |
| "area_rooms_interact": area_rooms_interact, | |
| "lat": lat, | |
| "lon": lon, | |
| "luxurious": int(luxurious), | |
| "furnished": int(furnished), | |
| "temporary": int(temporary), | |
| "zurich_city": int(zurich_city), | |
| "room_per_m2": room_per_m2, | |
| **kreis_cols, | |
| "(ATTIKA)": int(attika), | |
| "(LOFT)": int(loft), | |
| "(SEESICHT)": int(seesicht), | |
| "(LUXURIÖS)": 0, | |
| "(POOL)": 0, | |
| "(EXKLUSIV)": 0, | |
| } | |
| input_df = pd.DataFrame([input_dict])[features] | |
| prediction_log = model.predict(input_df)[0] | |
| prediction = np.expm1(prediction_log) | |
| return f"Estimated Monthly Rent: **CHF {prediction:,.0f}**" | |
| demo = gr.Interface( | |
| fn=predict_price, | |
| inputs=[ | |
| gr.Number(label="Number of Rooms", value=3.0), | |
| gr.Number(label="Living Area (m²)", value=80), | |
| gr.Number(label="Municipal Tax Income (CHF)", value=80000), | |
| gr.Checkbox(label="Luxurious"), | |
| gr.Checkbox(label="Furnished"), | |
| gr.Checkbox(label="Temporary"), | |
| gr.Checkbox(label="Located in Zurich City"), | |
| gr.Checkbox(label="Attika (Penthouse)"), | |
| gr.Checkbox(label="Loft"), | |
| gr.Checkbox(label="Lake View (Seesicht)"), | |
| gr.Dropdown( | |
| label="Zurich District (Kreis)", | |
| choices=["None"] + [f"Kreis {i}" for i in range(1, 13)], | |
| value="None" | |
| ), | |
| ], | |
| outputs=gr.Markdown(), | |
| submit_btn="Predict Rent", | |
| examples=[ | |
| [3.0, 80, 70000, False, False, False, True, False, False, False, "Kreis 3"], | |
| [4.5, 120, 120000, True, False, False, True, True, False, True, "Kreis 1"], | |
| [2.0, 55, 55000, False, True, False, False, False, False, False, "None"], | |
| ], | |
| title="Zurich Apartment Rent Predictor", | |
| description=( | |
| "Predict the monthly rental price for an apartment in the Canton of Zurich.\n\n" | |
| "This model uses a **Gradient Boosting Regressor** trained on ~800 Zurich apartment listings, " | |
| "with features including location (district), apartment characteristics, " | |
| "and the **Income-Density Score** (a neighbourhood affluence proxy)." | |
| ), | |
| theme=gr.themes.Soft(), | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |