Predict residential property prices across Tehran, Iran using machine learning. Features intrinsic USD modeling to insulate valuations from Rial currency hyperinflation, dynamic exchange-rate adaptation via environment variables, zero-leakage scikit-learn pipelines, and an interactive Streamlit web application.
-
Inflation-Resistant Modeling: By training directly on
Price(USD), the system captures fundamental real estate purchasing power, bypassing nominal Iranian Rial/Toman inflation drift. -
Dynamic Real-Time Conversion: Uses
USD_TO_TOMAN_RATE(configurable via.env/ environment variable) to project real-time Toman market prices for any macroeconomic timeframe. -
Champion Model Performance: Random Forest Regressor achieves a holdout test
$R^2$ of 0.822 across the full Tehran residential market (3,450 authentic listings). -
Zero Data Leakage: Custom feature engineering and
ColumnTransformerwithOneHotEncoder(min_frequency=5)andStandardScalerfitted strictly on training folds. -
Interactive Streamlit Web App: Launch an interactive real estate valuation dashboard with live exchange rate controls via
uv run streamlit run app.py. -
100% Self-Contained Notebook:
House_Price.ipynbcontains the complete analysis from raw data ingestion to model serialization with zero external script dependencies.
Models were systematically evaluated under 5-Fold Cross-Validation on training folds and tested on an independent 20% holdout test set:
| Model Architecture | Holdout |
MAE ($ USD) | RMSE ($ USD) | MedAE ($ USD) | MAPE (%) |
|---|---|---|---|---|---|
| Random Forest (Log Target) 🏆 | 0.822 | $51,889 | $122,216 | $18,851 | 35.1% |
| Linear Regression (Log Target) | 0.748 | $53,129 | $145,424 | $16,318 | 29.8% |
| Ridge Regression CV (Log Target) | 0.740 | $53,834 | $147,966 | $16,761 | 30.0% |
| ElasticNet CV (Log Target) | 0.719 | $55,870 | $153,585 | $17,391 | 31.2% |
| Baseline (Median Predictor) | -0.110 | $141,496 | $305,522 | $59,800 | 119.5% |
├── House_Price.ipynb # 100% self-contained end-to-end data science notebook
├── app.py # Interactive Streamlit valuation web application
├── model.joblib # Serialized champion model pipeline (trained on USD)
├── pyproject.toml # Project dependencies and configuration (managed by uv)
├── uv.lock # Locked dependency versions for exact reproducibility
├── .env.example # Template for environment variables (USD_TO_TOMAN_RATE)
├── .env # Local environment configuration
├── data/
│ ├── housePrice.csv # Raw dataset (tracked by DVC)
│ └── housePrice.csv.dvc # DVC metadata pointer
└── README.md # Project overview and instructions
- Python 3.13+
- uv — Fast Python package manager
- Git
git clone https://github.com/haadijafari/House-Price-Prediction.git
cd House-Price-Prediction
uv syncuv run dvc pullCopy the example environment file:
cp .env.example .envAdjust USD_TO_TOMAN_RATE to your desired market exchange rate (e.g. 60000 Tomans/USD).
Run the interactive property valuation dashboard:
uv run streamlit run app.pyOpen your browser at http://localhost:8501 to test custom property specs, compare against neighborhood median prices, and adjust exchange rates in real time.
Explore the full narrative, 10 before-and-after visual diagnostics, and training pipelines:
uv run jupyter notebookOpen House_Price.ipynb to inspect all pre-rendered charts and markdown documentation.
In high-inflation economies like Iran, real estate prices denominated in Iranian Tomans/Rials experience continuous nominal inflation. Training models directly in local currency causes rapid parameter decay. By modeling Price(USD) with logarithmic scaling ($\log(1 + \text{Price}_{USD})$):
- The target variable is normalized from a heavy right-skew of 4.77 to a near-Gaussian 0.06.
- Intrinsic property value is preserved across years.
- Real-time Toman market prices are calculated via: $$\text{Price}{\text{Toman}} = \widehat{\text{Price}}{\text{USD}} \times \text{USD_TO_TOMAN_RATE}$$
-
Area_per_Room: Living space density per bedroom ($\text{Area} / \max(\text{Room}, 1)$), separating compact units from luxury layouts. -
Total_Amenities: Composite score summing$\text{Parking} + \text{Warehouse} + \text{Elevator}$ ($0$ to$3$ ). -
Categorical Frequency Thresholding: Scikit-Learn's
OneHotEncoder(min_frequency=5)groups rare neighborhoods into an infrequent category, preventing high-cardinality overfitting.
- Language & Runtime: Python 3.13+, uv
- Machine Learning: scikit-learn (
TransformedTargetRegressor,Pipeline,ColumnTransformer,RandomForestRegressor,RidgeCV,ElasticNetCV) - Web Application: Streamlit
- Data Engineering: pandas, NumPy, DVC
- Data Visualization: Matplotlib, Seaborn
- Code Quality: Ruff linter & formatter
- Author: Haadi Jafari
- GitHub: @haadijafari
- Email: haadijafari2003@gmail.com