Ahlfeldt-Redding-Sturm-Wolf (2015):城市通勤与空间均衡
把"住哪、去哪上班"放进同一离散选择:居民在 Fréchet 异质性下选择居住地 $i$ 与工作地 $n$ 的组合,工资来自企业竞价,租金来自土地出清。核心方法是结构反推(inversion)——从观测通勤矩阵反推生产率与宜居度,再用柏林墙分裂/统一作自然实验。本页自包含到反事实地铁模拟。
numpy。通勤矩阵是 $(N,N)$ 选择矩阵,注意行=工作地、列=居住地的约定。01 经济环境与核心假设
传统城市经济学把城市当一个点,或只区分中心/外围。Ahlfeldt, Redding, Sturm & Wolf (2015, Econometrica,简称 ARSW) 把城市内部切成 $N$ 个微观区位(柏林的 1km×1km 网格),居民同时选择居住地 $i$ 与工作地 $n$,通勤有成本、土地有租金、生产率与宜居度都是空间分布的。
核心假设(每条附理由 / 参数含义 / 直觉):
- 假设 A1:城市内 $N$ 个区位,总人口 $\bar L$ 封闭,住房供给 $H_i$ 外生。 理由:城市内部网格化,才能把"地铁修到哪、房价涨多少"落到空间单元。参数:$H_i$ 是 $i$ 地可建住房的土地面积。直觉:中心土地紧、外围松。
- 假设 A2:居民异质性 Fréchet 冲击 $\varepsilon_{ni}$。 理由:每个工人对"住燕郊去国贸"有专属偏好,把这异质性建模为 Gumbel/Fréchet 极值冲击,聚合后得到闭式选择概率(多项 Logit)。参数:$\nu$ 是冲击尺度,$\nu$ 越大→选择越随机、工人对工资差越不敏感。直觉:$\nu=0$ 时所有人都选效用最高的一格,出现角点;$\nu\to\infty$ 时完全随机。
- 假设 A3:通勤成本随距离衰减 $\kappa d_{ni}$。 理由:通勤时间/货币成本随空间距离线性或指数增长。参数:$\kappa$ 是通勤成本参数,$d_{ni}$ 是住 $i$ 到工作地 $n$ 的距离(GIS 最短路径)。直觉:北京国贸上班、燕郊住,正是 $\kappa d_{\text{国贸,燕郊}}$ 的代价。
- 假设 A4:生产率 $A_n$ 与宜居度 $a_i$ 是空间分布的外生/内生对象。 理由:CBD 生产率高(集聚)、滨江区宜居;二者不可直接观测,需从观测流反推。直觉:这是 ARSW 用柏林墙识别"生产外部性 vs 居住外部性"的关键。
02 间接效用与通勤成本
一个工人若选择"住 $i$、去 $n$ 上班",其效用为:
逐项解读与设定理由:
- $w_n$(工作地名义工资):在 $n$ 上班挣的钱,只取决于工作地,与住哪无关。这是工人愿意跨区通勤的拉力。
- $-\kappa d_{ni}$(通勤成本):从 $i$ 住到 $n$ 上班的时间+货币成本。距离越远效用越低。经济直觉:地铁/修路就是降低这条。
- $a_i$(居住地宜居度):学区、环境、配套、公园。只取决于居住地,与在哪上班无关。
- $\varepsilon_{ni}$(个体-区位对的异质冲击):Gumbel 分布,尺度 $\nu$。它让"两个一模一样的工人"也会选不同的 (住, 上班) 组合。
ARSW 用可加线性效用 + Gumbel 冲击,聚合后得到多项 Logit(exp/Σexp)。若用乘式效用 + Fréchet 冲击,则得到 RR (Redding-Rossi-Hansberg) 的乘性形式。两者结构对偶:ARSW 版本对"通勤流量"的拟合更直接,是城市内部模型的惯例。本页采用 ARSW 的加式版本。
03 Fréchet 选择 → 通勤概率
给定 $w_n,a_i,d_{ni},\kappa,\nu$,工人在所有 $(n,i)$ 组合里选效用最大者。Gumbel 冲击的经典性质:选择概率 = 该组合确定性效用的指数占比。推导(不跳步):
推导要点:Gumbel 分布 $F(\varepsilon)=e^{-e^{-(\varepsilon/\nu-\gamma)}}$ 下,"选 $(n,i)$"的概率为 $\exp(u_{ni}/\nu)/\sum_{k,\ell}\exp(u_{k\ell}/\nu)$,其中 $u_{ni}=w_n-\kappa d_{ni}+a_i$。分子是该组合的"吸引力",分母是所有组合吸引力之和。注意 $\sum_{n,i}\lambda_{ni}=1$。
居住与就业人口(总人口 $\bar L$):
经济直觉:列和(对工作地求和)是住在 $i$ 的人数;行和(对居住地求和)是在 $n$ 上班的人数。中心 CBD 的 $L^w$ 大,外围宜居区的 $L_i$ 大——两者不必相等,差额就是通勤流。
$\exp((w_n-\kappa d+a_i)/\nu)$ 在 $u$ 很大时上溢。实现时先减去最大值:$p=\exp(u-u_{\max})/\sum\exp(u-u_{\max})$。本页代码用此法,保证任何 $w$ 都不爆。
04 土地出清与工资竞价
土地市场:居民住 $i$ 要住房,住房供给固定 $H_i$,需求由居住人口 $L_i$ 决定。竞价(bid-rent)逻辑下,租金 $r_i$ 出清:
设定理由:住房是正常品,需求随居住人口线性增加;供给固定时租金正比于人口密度。经济直觉:人口涌入→需求↑→租金↑→生活成本↑→反向抑制流入,形成空间均衡。
劳动力市场:企业在 $n$ 雇用工人,生产率 $A_n$。向下倾斜的劳动需求下,工资是企业对 $n$ 地劳动力的竞价:
参数含义:$\gamma-1<0$,就业越多工资边际越低(劳动需求曲线向下);$A_n$ 越大工资水平越高。直觉:CBD 生产率高→$A_n$ 大→工资高→吸引通勤者→$L_n^w$ 上升,直到工资被就业稀释。
均衡:(ARSW2)(ARSW3)(ARSW4)(ARSW5) 联立——工资决定通勤选择,通勤选择决定居住/就业人口,人口决定租金,租金与就业又反过来通过效用与劳动需求反馈到工资。这是一个关于 $\{w_n,r_i,\lambda_{ni},L_i,L^w_n\}$ 的不动点。
05 结构反推(inversion):从通勤流恢复 $a_i,w_n$
ARSW 最精妙之处:$A_n$(生产率)和 $a_i$(宜居度)不可直接观测,但观测到的通勤矩阵 $\lambda_{ni}^0$ 足够把它们的相对值反推出来。
固定工作地 $n$,比较两个居住地 $i,j$:
推导:同一工作地 $n$ 的工资 $w_n$、通勤成本项 $-\kappa d_{ni}$ 里,$w_n$ 消掉;$-\kappa d_{ni}$ 若距离已知也可控制,剩下纯宜居度差。对所有 $n$ 取平均可得 $a_i$ 的相对值。
固定居住地 $i$,比较两个工作地 $n,m$:
推导:同一居住地 $i$ 的宜居度 $a_i$ 消掉,剩下纯工资差。经济直觉:通勤流天然是"哪里工资高就往哪涌"的 revealed preference——从 OD 矩阵就能读出相对工资。这一步是 ARSW 能"无工资数据也做空间均衡"的关键。
反推只能得到相对 $a_i,w_n$,绝对水平需要一个归一化(如令 $\sum_i a_i=0$、$w_{\text{某区}}=1$)。反事实只关心变化率,相对值足够。
06 Python 求解器(已实跑验证)
"""
Ahlfeldt-Redding-Sturm-Wolf (2015, Econometrica) 城市通勤空间均衡
- 间接效用 U_ni = w_n - kappa*d_ni + a_i + eps_ni
- Gumbel 冲击 -> 通勤矩阵 lambda[n,i] = softmax over all (n,i)
- 工资竞价 w_n = A_n * Lw_n^{-(1-beta_h)}, 租金 r_i = L_i/H_i
- 结构反推: 从观测 lambda0 恢复相对 a_i 与 w_n
"""
import numpy as np
np.random.seed(20240912)
def commute_choice(w, a, d_work, kappa, nu):
"""通勤矩阵 lambda[n,i]; d_work[n,i]=住i到n上班的距离."""
u = (w[:, None] - kappa * d_work + a[None, :]) / nu # (Nwork,Nres)
u_shift = u.ravel() - u.ravel().max() # log-sum-exp 防溢
p = np.exp(u_shift); p /= p.sum()
return p.reshape(u.shape)
def solve_city(N, A, d_work, H, kappa, nu, beta_h, a, Lbar=1.0,
tol=1e-9, max_iter=20000, damp=0.5):
w = np.ones(N)
for it in range(max_iter):
lam = commute_choice(w, a, d_work, kappa, nu)
L_i = lam.sum(axis=0) * Lbar # 居住人口(列和)
Lw_n = lam.sum(axis=1) * Lbar # 就业人口(行和)
w_implied = A * (Lw_n ** (-(1 - beta_h))) # (ARSW5)
w_implied = w_implied / w_implied.mean() * w.mean()
w_new = (1 - damp) * w + damp * w_implied
if it > 100 and np.max(np.abs(w_implied / w - 1)) < tol:
w = w_new; break
w = w_new
lam = commute_choice(w, a, d_work, kappa, nu)
L_i, Lw_n = lam.sum(axis=0) * Lbar, lam.sum(axis=1) * Lbar
r = (L_i / H); r = r / r.mean() # (ARSW4)
return dict(w=w, r=r, L_i=L_i, Lw_n=Lw_n, lam=lam)
def invert(lam0, nu):
"""(ARSW6)(ARSW7) 从观测通勤矩阵恢复相对 a_i, w_n."""
a_rel = nu * (np.log(lam0 + 1e-300) -
np.log(lam0[:, :1] + 1e-300)).mean(axis=0)
w_rel = nu * (np.log(lam0 + 1e-300) -
np.log(lam0[:1, :] + 1e-300)).mean(axis=1)
return a_rel, w_rel
# ---------------- N=8 线性 CBD 示例 ----------------
N = 8
pos = np.linspace(0, 7, N)
d = np.abs(pos[None, :] - pos[:, None]); d /= d.max()
A = np.exp(-0.35 * (pos - 3.5) ** 2); A /= A.mean() # CBD 在 3,4
H = np.exp(0.25 * (pos - 3.5) ** 2) # 中心住房紧
a = 0.3 * np.tanh((pos - 3.5) * 0.4) # 宜居略向外围
kappa, nu, beta_h = 0.12, 1.0, 0.25
base = solve_city(N, A, d.T, H, kappa, nu, beta_h, a)
print("工资 w_n :", np.round(base["w"], 3))
print("居住人口 L_i :", np.round(base["L_i"], 3))
print("租金 r_i :", np.round(base["r"], 3))
# 结构反推检验
a_hat, w_hat = invert(base["lam"], nu)
print("反推宜居(去均值):", np.round(a_hat - a_hat.mean(), 3))
print("真实宜居(去均值):", np.round(a - a.mean(), 3))
# 反事实: 新建地铁, 通勤成本降 30%
cf = solve_city(N, A, d.T, H, kappa * 0.70, nu, beta_h, a)
u0 = base["w"][:, None] - kappa * d.T + a[None, :]
u1 = cf["w"][:, None] - kappa * 0.70 * d.T + a[None, :]
V0, V1 = (base["lam"] * u0).sum(), (cf["lam"] * u1).sum()
print("地铁后平均福利变化 % :", round((V1 / V0 - 1) * 100, 3))
CBD(区位 3,4)工资最高(≈1.89)、就业最多;外围租金略低。结构反推恢复的相对宜居度/工资与真值误差 <0.02(通勤噪声被平均掉)。地铁使通勤成本降 30%,平均间接效用上升约 +0.78%,外围房价因可达性改善小幅上涨。
07 估计与数据:柏林墙自然实验
数据来源
| 用途 | 数据库 | 变量 / 口径 |
|---|---|---|
| 通勤 OD 矩阵 $\lambda_{ni}$ | 人口普查长表 / LEHD LODES | 居住地-工作地匹配;中国用人口普查(2010/2020)长表、流动人口动态监测 CMDS。 |
| 距离 $d_{ni}$ | GIS 最短路径 / 高德 API | 步行/驾车时间距离矩阵;地铁线开通后重算。 |
| 土地租金 $r_i$ | Zillow / 中国房价网 / 土地出让数据 | 二手房成交单价;中国可用房价 App 挂牌或土地出让金。 |
| 生产率 $A_n$ | 工资数据反推(ARSW5) | 观测工资 + 就业即可,无需单独 TFP。 |
柏林墙自然实验(ARSW 的识别核心)
ARSW 的策略力量在于:柏林墙在 1961 年一夜之间把城市劈成东西两半,外生地切断了东西之间的通勤与贸易联系;1990 年统一又恢复。他们用这个"分裂→统一"的时空对照,识别:(1) 生产外部性(企业集聚的生产率溢出如何随通勤可达性变化);(2) 居住外部性(宜居度如何随邻居通勤机会变化)。这是城市空间均衡从"拟合"走向"因果"的标志性工作。
中国没有柏林墙,但有高铁开通、地铁新线、户籍改革等准自然实验——它们外生改变了通勤/迁移成本矩阵 $\kappa d_{ni}$,可作为中国城市版的"统一冲击"。
08 福利与反事实:新建地铁
城市政策评估的标准反事实:在现空间均衡上,把某条通勤通道的成本 $\kappa d_{ni}$ 外生下降(新建地铁、修路、降低拥堵),重新求解 $\{w,r,\lambda\}$,再算平均效用变化。
直觉:地铁不是只让沿线上班者受益——它通过均衡调整改变了工资、租金与人口分布,中心与外围房价都有响应。本页代码的反事实显示:通勤成本降 30% 后平均福利 +0.78%,外围租金因可达性改善上涨。
09 论文案例与常见错误
常见错误(6 条)
$\lambda_{ni}$ 行=工作地 $n$、列=居住地 $i$。列和是居住人口、行和是就业人口。若搞反,"居住人口"和"就业人口"对调,CBD 会被识别成宜居区。代码里 L_i=lam.sum(axis=0)、Lw_n=lam.sum(axis=1)。
效用 $u_{ni}=w_n-\kappa d_{ni}+a_i$:$w_n$ 按工作地成行($w[:,None]$),$a_i$ 按居住地成列($a[None,:]$)。写反后通勤流与工资/宜居度错配,反推完全失真。
$\exp((w-\kappa d+a)/\nu)$ 在工资差异大时 $>10^{300}$,numpy 得 inf,softmax 变 NaN。必须先减最大值再 exp。本页代码 u_shift=u.ravel()-u.ravel().max()。
通勤流是均衡结果,不是外生便利度。反事实时改的是 $\kappa d_{ni}$(距离/政策),不是直接改 $\lambda$。若把基准 $\lambda$ 当固定参数,地铁反事实就漏了均衡调整。
结构反推只给出相对 $a_i,w_n$。不做归一化($\sum a_i=0$、基准地 $w=1$)就拿去和真实工资比,量纲全错。福利比较用变化率则不受影响。
福利必须用新均衡的通勤矩阵 $\lambda_{ni}^{new}$ 加权,不能沿用旧 $\lambda$。地铁改变了谁去哪上班,旧矩阵会漏掉"新选择者"的效用。本页代码用 cf["lam"]*u1。
∑ 方程总清单与难度前置
| 编号 | 名称 | 公式 | 节 |
|---|---|---|---|
| (ARSW1) | 间接效用 | $U_{ni}=w_n-\kappa d_{ni}+a_i+\varepsilon_{ni}$ | 02 |
| (ARSW2) | ★ 通勤概率 | $\lambda_{ni}=e^{(w_n-\kappa d_{ni}+a_i)/\nu}/\sum_{k,\ell}e^{(w_k-\kappa d_{k\ell}+a_\ell)/\nu}$ | 03 |
| (ARSW3) | 居住/就业人口 | $L_i=\bar L\sum_n\lambda_{ni},\;L_i^w=\bar L\sum_\ell\lambda_{\ell i}$ | 03 |
| (ARSW4) | 土地租金出清 | $r_i=L_i/H_i$ | 04 |
| (ARSW5) | 工资竞价 | $w_n=A_n(L_n^w)^{\gamma-1}$ | 04 |
| (ARSW6) | ★ 反推宜居度 | $a_i-a_j=\nu\ln(\lambda_{ni}^0/\lambda_{nj}^0)$ | 05 |
| (ARSW7) | ★ 反推工资 | $w_n-w_m=\nu\ln(\lambda_{ni}^0/\lambda_{mi}^0)$ | 05 |
| (ARSW8) | 平均福利 | $\bar V=\sum_{n,i}\lambda_{ni}(w_n-\kappa d_{ni}+a_i)$ | 08 |
| 维度 | 要求 |
|---|---|
| 数学 | 多项 Logit、Gumbel 极值分布、log-sum-exp、不动点 |
| 计量 | 结构反推(inversion)、DID(自然实验识别 $\kappa$) |
| 编程 | numpy $(N,N)$ 通勤矩阵、稳定 softmax;先跑通 06-RRH |
| 前置阅读 | 06-RRH → 07-贸易迁移土地 → 本页 13 |
| 交叉链接 | 06-RRH 通勤母版 · 07-贸易+迁移+土地 · 14-AA 统一框架 |