# 🏠 Hedonic House Pricing with Language-Model and Vision Features **UQO Working Paper No. 14** β€” *Evidence from Quebec Real-Estate Listings* [![Paper](https://img.shields.io/badge/paper-PDF%20(33%20p.)-b31b1b?logo=latex&logoColor=white)](paper/main.pdf) [![Python](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](requirements.txt) [![Data](https://img.shields.io/badge/data-19%2C123%20house%20listings%20Β·%20Realtor.ca%20%2B%20DuProprio-4051b5)](data/raw/README.md) [![Reproducible](https://img.shields.io/badge/reproducible-end--to--end%20pipeline-2e7d32)](scripts/) [![Institution](https://img.shields.io/badge/UQO-D%C3%A9pt.%20des%20sciences%20administratives-16365c)](https://uqo.ca) [![Author](https://img.shields.io/badge/author-Simon--Pierre%20Boucher-16365c)](mailto:simon-pierre.boucher@uqo.ca) > **TL;DR** β€” Much of a home's value is recorded only in the free text and the photographs of its listing. We use a > large language model to turn each description into structured specifications and a vision–language model to turn the > faΓ§ade photo into objective visual attributes, both under strict JSON schemas. On 19,123 Quebec house listings the two > AI layers lift the RΒ² of an already rich log-linear hedonic model from 0.717 to 0.755; the vision layer is the largest > out-of-sample gain of any feature block for every estimator (OLS, gradient boosting, neural nets); the best ensemble > reaches out-of-sample RΒ² 0.779 with a 14.0% median absolute error. Implicit prices are economically sensible (+2.3% per > point of curb appeal, +3–4% for brick or stone) and survive municipality-clustered inference. --- ## πŸ“Œ Status | Item | Value | |---|---| | Version | 2.0 (July 2026) β€” revised draft after an internal review round (`scripts/13_revision_extras.py`) | | SSRN | not yet submitted | | Journal | Elsevier-format highlights prepared (`docs/highlights_elsevier.tex`); target to be decided | | Code & data | reproducible from `scripts/` run from the repository root; raw crawls and LLM caches not committed | ## 🎯 What this paper does Hedonic models are bounded by the characteristics an analyst can measure. We treat general-purpose AI models as a **feature-engineering technology**: each listing description is parsed by an LLM into a fixed schema of property specifications (renovations, finishes, systems, extras), and each faΓ§ade photograph is parsed by a vision–language model into objective attributes (cladding, storeys, garage, curb appeal). The outputs are ordinary econometric variables and enter a log-linear hedonic regression with city fixed effects: ``` ln P_i = Ξ±_city(i) + X_i'Ξ² + S_i'Ξ³ (LLM text layer) + V_i'Ξ΄ (vision layer) + Ξ΅_i ``` We then measure, under identical 5-fold splits, how much each layer adds for OLS, histogram gradient boosting, a residual MLP with city/type embeddings, and a stacked blend. ## πŸ† Headline results | Object | Estimate | |---|---| | Base hedonic OLS (structural + location), in-sample RΒ² | 0.717 | | + LLM text layer + vision layer | 0.755 | | Out-of-sample RΒ², OLS: base β†’ +text β†’ +text+vision (5-fold) | 0.52 β†’ 0.62 β†’ … (see `paper/tables/ablation.tex`) | | Out-of-sample RΒ², GBM: base β†’ +text | 0.69 β†’ 0.73 | | Best ensemble (robust NN + GBM blend) | RΒ²_OOS = 0.779, median absolute error 14.0% | | Curb-appeal score (1–5) | +2.3% per point | | Brick / stone faΓ§ade | +3–4% | | Inference | HC3 and municipality-clustered standard errors agree | ## πŸ—‚ Repository layout ``` hedonic-llm-vision-features/ β”œβ”€β”€ data/ β”‚ β”œβ”€β”€ raw/ # two Apify crawls (Realtor.ca, DuProprio), 2026-07-03 β€” not committed β”‚ └── processed/ # LLM/vision caches, merged datasets, OOS predictions β€” not committed β”œβ”€β”€ scripts/ # run from the repository root, in order β”‚ β”œβ”€β”€ 00a_test_openai_extraction.py / 00b_test_vision_claude.py # API smoke tests β”‚ β”œβ”€β”€ 01_extract_specs_llm.py # description β†’ JSON specs (parallel, resumable) β”‚ β”œβ”€β”€ 02_facade_vision.py # faΓ§ade photo β†’ visual attributes β”‚ β”œβ”€β”€ 03_merge_llm_features.py β”‚ β”œβ”€β”€ 04_hedonic_ols_base.py / 05_hedonic_ols_v4_text.py β”‚ β”œβ”€β”€ 06_hedonic_ml_cv.py / 07_torch_nn.py / 08_torch_nn_robust.py β”‚ β”œβ”€β”€ 09_v5_ml_text_vision.py / 10_final_blend.py β”‚ β”œβ”€β”€ 11_extras_v5_robustness.py / 12_ablation_extras.py / 13_revision_extras.py β”‚ └── 14_figures_v5.py / 15_make_tables.py / 16_make_tables_v5.py / 17_gen_regression_table.py β”œβ”€β”€ results/ # hedonic summaries (txt), ablation_extras.json, revision_extras.json β”œβ”€β”€ docs/ # METHODOLOGIE.md + methodologie.tex/pdf (French data & method note), Elsevier highlights └── paper/ # main.tex + sections/ + tables/ + figures/ + references.bib β†’ main.pdf ``` ## πŸš€ Quick start ```bash python3 -m pip install -r requirements.txt cp .env.example .env # OPENAI_API_KEY=…, ANTHROPIC_API_KEY=… (only steps 00–02 call the APIs) # place the two Apify crawls in data/raw/ and build data/processed/maisons_avec_prix.json (docs/METHODOLOGIE.md Β§2–4), then: WORKERS=24 python3 scripts/01_extract_specs_llm.py python3 scripts/02_facade_vision.py python3 scripts/03_merge_llm_features.py python3 scripts/05_hedonic_ols_v4_text.py python3 scripts/08_torch_nn_robust.py && python3 scripts/09_v5_ml_text_vision.py && python3 scripts/10_final_blend.py python3 scripts/11_extras_v5_robustness.py && python3 scripts/12_ablation_extras.py && python3 scripts/13_revision_extras.py python3 scripts/14_figures_v5.py && python3 scripts/16_make_tables_v5.py && python3 scripts/17_gen_regression_table.py cd paper && make # latexmk β†’ main.pdf ``` LLM extraction β‰ˆ 600 tokens in / 110 out per listing (24 threads); vision β‰ˆ 2,470 tokens in per image (16 threads); both are resumable. Econometrics and ML β‰ˆ 20 minutes on an Apple-silicon laptop (PyTorch on MPS). ## πŸ—ƒ Data 27,302 Realtor.ca and 7,693 DuProprio listings crawled on 2026-07-03; houses (single-family and townhouse) with a valid price retained, outliers removed by the rules in `docs/METHODOLOGIE.md` Β§3, giving 19,123 observations. Structural variables (living area, lot, rooms, year built, type, city), text-derived specifications and faΓ§ade attributes. See `data/raw/README.md` and `data/processed/README.md`. ## πŸ”¬ Methodology 1. **AI feature layers** with strict JSON schemas and retry/backoff β€” `scripts/01_…`, `scripts/02_…`. 2. **Log-linear hedonic OLS** with city fixed effects, HC3 and municipality-clustered SEs β€” `scripts/05_…`, `scripts/13_…`. 3. **Ablation by feature block Γ— estimator** under identical folds (OLS, GBM, NN) β€” `scripts/09_…`, `scripts/12_…`. 4. **Stacked blend** of the robust NN and HistGradientBoosting β€” `scripts/10_final_blend.py`. 5. **Robustness** by segment, extreme city effects, calibration and importance plots β€” `scripts/11_…`, `scripts/14_…`. ## πŸ–Ό Figures & tables inventory | Figure | Content | |---|---| | `fig_ablation` | out-of-sample gain by feature block and estimator | | `fig_calibration` | predicted vs actual, blend | | `fig_importance` | feature importance | | `fig_premia` | location premia | | `fig_validation` | validation of AI-extracted attributes | | `nn_diagram` (TikZ) | architecture of the robust NN | Tables (`paper/tables/*.tex`): summary stats, regression (A/B panels), models, ablation, robustness, AI summary. ## ⚠️ Limitations - Asking prices from listings, single cross-section (July 2026). - Realtor.ca listings lack coordinates; location enters through city fixed effects and postal codes. - LLM/vision outputs are model-dependent; schemas and prompts are versioned in the scripts. - API costs make the extraction layers the expensive part of replication. ## πŸ“ Citation ```bibtex @techreport{boucher2026llmvisionhedonic, author = {Boucher, Simon-Pierre}, title = {Hedonic House Pricing with Language-Model and Vision Features: Evidence from Quebec Real-Estate Listings}, institution = {Universit\'e du Qu\'ebec en Outaouais, D\'epartement des sciences administratives}, type = {Working Paper}, number = {14}, year = {2026}, month = {July} } ``` ## πŸ‘€ Author & contact **Simon-Pierre Boucher** β€” DΓ©partement des sciences administratives, UniversitΓ© du QuΓ©bec en Outaouais (UQO), Gatineau, QC. πŸ“§ [simon-pierre.boucher@uqo.ca](mailto:simon-pierre.boucher@uqo.ca) ## πŸ—’ Notes - Numbering: this paper was first issued as "Working Paper No. 11" (July 2026); number 11 belongs to *Half a Million Prices, Twenty Models*. Renumbered **14** on 2026-10-17; cover date fixed to July 2026 (was `\today`). - Harmonised 2026-10-17: flat scripts moved to `scripts/` (numbered), data to `data/`, logs removed, summaries to `results/`, methodology note to `docs/`; file paths inside the scripts now point to `data/…` and `results/…` (run them from the repository root). Bibliography switched from `plainnat` to `aer`. - The script `13_revision_extras.py` was written for a Journal of Housing Economics revision round (clustered SEs, in-sample ablation, extreme city effects).