Spaces:
Sleeping
Sleeping
File size: 4,290 Bytes
3fdedfb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | import pickle
from pathlib import Path
import pandas as pd
import streamlit as st
st.set_page_config(page_title="UrbanNest Rent Predictor", layout="wide")
ARTIFACT_DIR = Path("models")
INFERENCE_BUNDLE_PATH = ARTIFACT_DIR / "inference_bundle.pkl"
UNKNOWN_CATEGORY_TOKEN = "__UNK__"
@st.cache_resource
def load_inference_artifacts():
if not INFERENCE_BUNDLE_PATH.exists():
raise FileNotFoundError(
"Missing models/inference_bundle.pkl. Run train.ipynb first."
)
with open(INFERENCE_BUNDLE_PATH, "rb") as f:
bundle = pickle.load(f)
required_keys = {"model", "label_encoders", "feature_columns", "feature_metadata", "model_metadata"}
missing_keys = required_keys - set(bundle.keys())
if missing_keys:
raise KeyError(f"inference_bundle.pkl is missing keys: {sorted(missing_keys)}")
return (
bundle["model"],
bundle["label_encoders"],
bundle["feature_columns"],
bundle["feature_metadata"],
bundle["model_metadata"],
)
def _build_numeric_input(feature_name, metadata):
dtype = metadata["dtype"]
min_value = metadata["min"]
max_value = metadata["max"]
default_value = metadata["mean"]
if "int" in dtype:
return st.number_input(
label=feature_name,
min_value=int(min_value),
max_value=int(max_value),
value=int(round(default_value)),
step=1,
)
return st.number_input(
label=feature_name,
min_value=float(min_value),
max_value=float(max_value),
value=float(default_value),
step=0.1,
format="%.4f",
)
def main():
st.title("UrbanNest Analytics: Dynamic House Rent Prediction")
st.write("Provide property details below to estimate monthly rent (INR).")
try:
model, label_encoders, feature_columns, feature_metadata, model_metadata = load_inference_artifacts()
except Exception as exc:
st.error(f"Failed to load model artifacts: {exc}")
st.stop()
st.caption(
f"Best training method: {model_metadata['best_method']} | "
f"CV MAE: {model_metadata['best_cv_mae']:.2f} | "
f"Test MAE: {model_metadata['test_mae']:.2f}"
)
user_inputs = {}
left_col, right_col = st.columns(2)
column_index = 0
for feature_name in feature_columns:
target_column = left_col if column_index % 2 == 0 else right_col
with target_column:
if feature_name in label_encoders:
classes = [str(item) for item in label_encoders[feature_name].classes_]
if UNKNOWN_CATEGORY_TOKEN in classes:
display_options = [c for c in classes if c != UNKNOWN_CATEGORY_TOKEN]
display_options.append("Other / Unknown")
user_inputs[feature_name] = st.selectbox(feature_name, options=display_options)
else:
user_inputs[feature_name] = st.selectbox(feature_name, options=classes)
else:
user_inputs[feature_name] = _build_numeric_input(feature_name, feature_metadata[feature_name])
column_index += 1
if st.button("Predict"):
encoded_row = {}
for feature_name in feature_columns:
feature_value = user_inputs[feature_name]
if feature_name in label_encoders:
raw_value = str(feature_value)
if raw_value == "Other / Unknown":
raw_value = UNKNOWN_CATEGORY_TOKEN
encoded_row[feature_name] = int(label_encoders[feature_name].transform([raw_value])[0])
else:
dtype = feature_metadata[feature_name]["dtype"]
if "int" in dtype:
encoded_row[feature_name] = int(feature_value)
else:
encoded_row[feature_name] = float(feature_value)
model_input = pd.DataFrame([encoded_row], columns=feature_columns)
prediction = float(model.predict(model_input)[0])
st.success(f"Predicted Monthly Rent: INR {prediction:,.2f}")
if __name__ == "__main__":
main()
|