SPB Git forge

spb/wp14_uqo

Public
1commits 1branches 0releases
897.0 KBsize
maindefault branch
1 h agolast push
Python 57% TeX 42.9%
ZIP tar.gz
NameLast commitUpdated
data harmonisation standard UQO WP (2026-10-17) 1 h ago
docs harmonisation standard UQO WP (2026-10-17) 1 h ago
paper harmonisation standard UQO WP (2026-10-17) 1 h ago
results harmonisation standard UQO WP (2026-10-17) 1 h ago
scripts harmonisation standard UQO WP (2026-10-17) 1 h ago
.env.example harmonisation standard UQO WP (2026-10-17) 1 h ago
.gitignore harmonisation standard UQO WP (2026-10-17) 1 h ago
README.md harmonisation standard UQO WP (2026-10-17) 1 h ago
requirements.txt harmonisation standard UQO WP (2026-10-17) 1 h ago
README.md source

# 🏠 Hedonic House Pricing with Language-Model and Vision Features

UQO Working Paper No. 14 — Evidence from Quebec Real-Estate Listings

Paper Python Data Reproducible Institution Author

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:

text
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

text
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

# 🗒 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).