#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Régénère les tableaux LaTeX du papier en v5 (texte GPT + vision).""" import numpy as np, pandas as pd, statsmodels.formula.api as smf, warnings warnings.filterwarnings("ignore") # construire df via le pipeline de v5_ml (jusqu'avant la CV) exec(open("v5_ml.py").read().split("kf=KFold")[0]) amen_=list(AMEN.keys()) df["ln_price"]=np.log(df["price"]) df["ln_sqft"]=np.log(df["sqft_final"].fillna(df.groupby("ptype")["sqft_final"].transform("median")).fillna(df["sqft_final"].median())) df["ln_lot"]=np.log(df["lot_sqft"].fillna(df["lot_sqft"].median()));df["has_lot"]=df["lot_sqft"].notna().astype(int) df["has_age"]=df["age"].notna().astype(int) for c in ["beds","baths","storeys","age","age2"]: df[c]=df[c].fillna(df.groupby("ptype")[c].transform("median")).fillna(df[c].median()) df["parking"]=df["parking"].fillna(0) form=("ln_price ~ ln_sqft+ln_lot+has_lot+beds+baths+parking+storeys+age+age2+has_age+C(source)+C(ptype_fe)+" +"+".join(amen_)+"+n_images_c+virtual_tour+"+"+".join(rv)+"+"+"+".join(gv)+"+"+"+".join(vv)+"+C(city_fe)") mA=smf.ols(form,data=df[df["has_sqft"]==1]).fit(cov_type="HC3") mB=smf.ols(form.replace("ln_sqft+",""),data=df).fit(cov_type="HC3") print("A R2=%.4f adj=%.4f N=%d | B R2=%.4f adj=%.4f N=%d"%(mA.rsquared,mA.rsquared_adj,mA.nobs,mB.rsquared,mB.rsquared_adj,mB.nobs)) def star(p): return "^{***}" if p<.01 else "^{**}" if p<.05 else "^{*}" if p<.1 else "" def cell(m,k): if k not in m.params.index: return "","" b=m.params[k];se=m.bse[k];p=m.pvalues[k];s="$-$" if b<0 else "" return f"{s}{abs(b):.3f}${star(p)}$",f"({se:.3f})" disp=[("ln_sqft",r"$\ln(\text{Living area})$"),("ln_lot",r"$\ln(\text{Lot area})$"), ("beds","Bedrooms"),("baths","Bathrooms"),("parking","Parking"),("age","Age"), ("__A__","\\textit{Amenities \\& text (LLM)}"), ("central_air","Central A/C"),("transit","Public transit"),("waterfront","Waterfront"), ("g_cond","Condition (LLM, ord.)"),("g_renovated_kitchen","Reno.\\ kitchen (LLM)"), ("g_hardwood","Hardwood floor (LLM)"),("g_new_construction","New construction (LLM)"), ("g_income_property","Income property (LLM)"), ("__V__","\\textit{Vision (façade)}"), ("v_curb","Curb appeal (1--10)"),("v_reno","Renovation level (ord.)"), ("v_luxury","Luxury (visual)"),("v_garage_vis","Garage visible"), ("v_mat_brique","Brick façade"),("v_mat_pierre","Stone façade"), ("v_mat_vinyle","Vinyl façade"),("v_set_rural","Rural setting")] L=[] for k,lab in disp: if k in ("__A__","__V__"): L.append(f" \\multicolumn{{3}}{{@{{}}l}}{{{lab}}} \\\\[2pt]");continue a1,a2=cell(mA,k);b1,b2=cell(mB,k) L.append(f" {lab} & {a1} & {b1} \\\\") L.append(f" & {a2} & {b2} \\\\[3pt]") reg=r"""% Auto-generated v5 \begin{table}[htbp] \centering \begin{threeparttable} \caption{Hedonic Regression Results (Text + Vision Features)} \label{tab:regression} \begin{tabular}{@{}lcc@{}} \toprule & (1) Model~A & (2) Model~B \\ & \textit{rich} & \textit{broad} \\ \midrule """+"\n".join(L)+r""" \midrule City FE / Type FE & Yes & Yes \\ Living area & Yes & No \\ Observations & """+f"{int(mA.nobs):,}".replace(",","{,}")+r""" & """+f"{int(mB.nobs):,}".replace(",","{,}")+r""" \\ $R^2$ & """+f"{mA.rsquared:.3f}"+r""" & """+f"{mB.rsquared:.3f}"+r""" \\ Adjusted $R^2$ & """+f"{mA.rsquared_adj:.3f}"+r""" & """+f"{mB.rsquared_adj:.3f}"+r""" \\ \bottomrule \end{tabular} \begin{tablenotes}[flushleft] \footnotesize \item \textit{Notes:} OLS estimates of Equation~\eqref{eq:hedonic} with the full feature set. Model~A includes $\ln(\text{Living area})$ (measured-area subsample); Model~B omits it (full sample). ``LLM'' variables are extracted from the description text; ``Vision'' variables from the façade photograph. Curb appeal and renovation level enter as scores; luxury, garage, and material/setting are indicators. All specifications include city and property-type fixed effects and the full amenity, room-detail, and listing-signal controls (only selected coefficients shown). HC3 standard errors in parentheses. $^{***}$, $^{**}$, $^{*}$: significance at 1\%, 5\%, 10\%. \end{tablenotes} \end{threeparttable} \end{table} """ open("paper/tables/regression.tex","w").write(reg) print("-> paper/tables/regression.tex (v5)") # ---- models.tex : deux panels (texte / +vision) avec chiffres CV ---- models=r"""% Auto-generated v5 \begin{table}[htbp] \centering \begin{threeparttable} \caption{Predictive Performance: From OLS to Deep Learning} \label{tab:models} \begin{tabular}{@{}lcccc@{}} \toprule Estimator & $R^2_{\text{OOS}}$ & Median AE & Within $\pm$15\% & Within $\pm$25\% \\ \midrule \multicolumn{5}{@{}l}{\textit{Panel A: Structural + amenity + LLM-text features}} \\[3pt] OLS (linear hedonic) & 0.628 & 17.9\% & 43\% & 64\% \\ Random Forest & 0.678 & 18.0\% & 43\% & 64\% \\ Neural network (plain MLP) & 0.711 & 16.1\% & 47\% & 69\% \\ Neural network (robust ResNet) & 0.741 & 15.2\% & 49\% & 70\% \\ Gradient boosting (HistGBM) & 0.743 & 15.4\% & 49\% & 70\% \\ Blend (NN + GBM) & 0.760 & 14.7\% & 51\% & 72\% \\[4pt] \multicolumn{5}{@{}l}{\textit{Panel B: \ + Vision (façade) features}} \\[3pt] Gradient boosting (HistGBM) & 0.770 & 14.5\% & 51\% & 71\% \\ Neural network (robust ResNet) & 0.747 & 14.8\% & 51\% & 71\% \\ \textbf{Blend (NN + GBM)} & \textbf{0.779} & \textbf{14.0\%} & \textbf{53\%} & \textbf{73\%} \\ \bottomrule \end{tabular} \begin{tablenotes}[flushleft] \footnotesize \item \textit{Notes:} Out-of-sample performance from 5-fold cross-validation with a common seed (identical folds across rows). $R^2_{\text{OOS}}$ is on $\ln(\text{Price})$; ``Median AE'' is the median absolute percentage error in levels (Equation~\ref{eq:cvmetrics}). Panel~A uses structural, amenity, room-detail, listing-signal, and LLM text-derived features; Panel~B adds the twelve façade vision attributes. City, type, and source enter as one-hot indicators for the linear and tree models and as learned embeddings for the neural networks. The tree and neural models handle missing living area natively. The best model is the text\,+\,vision blend. \end{tablenotes} \end{threeparttable} \end{table} """ open("paper/tables/models.tex","w").write(models) print("-> paper/tables/models.tex (v5, 2 panels)")