📝 本模型共 10 个方程(含目标函数、Bellman 方程、选择特定价值、CCP、Rust 条件独立假设、NFXP 似然、Bellman 算子压缩、VFI 迭代、HM 反转与正向模拟)· 文末附「方程总清单 Equation Summary」
📚 前置条件与学习依赖 / Prerequisites
① 数学/统计基础:动态规划(Bellman 方程)、值函数迭代(VFI)、随机动态规划的收缩性;NFXP(nested fixed point,内层 Bellman 不动点 + 外层 MLE/GMM);Hotz–Miller CCP(条件选择概率)两步估计;折现因子与状态转移。
② 经济学理论前置:动态离散选择(DDCM):劳动经济学(退休、职业转换)、产业组织(企业进入/退出、设备更新如 Rust 1987 bus engine)、存货与投资。
③ 软件/计算前置:MATLAB 或 Python(值函数迭代 + 外层似然优化,计算密集;建议熟悉稀疏状态空间与向量化);Rust (1987) 经典 bus 数据是基准。
④ 站内前置页面:先学 01 MLE + 03 离散选择总览,动态模型本质是「跨期 MLE + Bellman」。
⑤ 难度分级:前沿

01 为什么需要动态模型:静态选择的局限

前几页讲的离散选择模型(logit、BLP)都是静态的:消费者在每个时期独立地最大化当期效用,今天的选择不影响明天的状态。但现实中大量决策是动态的:

  • 换不换公交车发动机?换了要花一笔钱,但发动机变新;不换,下个月可能坏在路上。
  • 要不要生孩子?今天生孩子会影响未来 20 年的劳动供给与消费。
  • 是否参与社保 / 退休?今天的退休决定了未来一辈子的收入流。
  • 企业何时进入/退出市场?进入是沉没成本,但决定了未来的利润流。
  • 研发投入 / 技术升级?今天的投入影响未来的生产率。

在这些问题里,当前决策改变了未来的状态分布,决策者必须比较"今天的效用 + 贴现后的未来价值"。这就是动态离散选择模型(Dynamic Discrete Choice Model, DDCM)

💡 与静态模型的本质区别

静态 logit 里,选择概率只取决于当期效用差;DDCM 里,选择概率取决于"当期效用 + 未来价值函数"之差。价值函数本身又是选择概率和状态转移的不动点——这就把"估计"变成了"嵌套不动点问题"。

02 动态离散选择框架(DDCM)

2.1 基本要素

一个标准的 DDCM 由以下要素构成:

  • 决策者(agent):在每个离散时期 $t = 1,2,\dots$ 做选择;
  • 状态变量 $x_t \in \mathcal{X}$:随时间演化的状态(如 bus 的里程、家庭的孩子数);
  • 选择集 $d_t \in \mathcal{D}(x_t)$:从状态 $x_t$ 出发可做的离散动作;
  • 当期效用 $u(x_t, d_t)$:选择 $d_t$ 时的 flow utility;
  • 转移概率 $p(x_{t+1} | x_t, d_t)$:选择 $d_t$ 后状态如何演化;
  • taste shock $\varepsilon_{t,d}$:每个选择的 i.i.d. 极端价值偏好冲击(和 logit 一样);
  • 贴现因子 $\beta \in (0,1)$:未来效用的贴现率。

2.2 决策者的目标函数

决策者在每一期选择 $d_t$ 来最大化贴现后的期望效用:

Equation 2.1 — 期望贴现效用
$$\max_{\{d_t\}} \; \mathbb{E}\left[\sum_{t=0}^{\infty} \beta^t \left( u(x_t, d_t) + \varepsilon_{t,d_t} \right) \;\middle|\; x_0, \varepsilon_0 \right]$$

由于问题是马尔可夫的(转移只依赖当期状态和选择),最优决策可以用 Bellman 方程递归刻画。

2.3 Rust (1987) 的识别假设:条件独立与充分性

Rust 证明 DDCM 可被部分识别依赖两个关键假设,这是 NFXP 可估计的前提,必须明确写出:

Equation 2.2b — Rust 条件独立性(Conditional Independence, 补全)
$$p(x_{t+1},\varepsilon_{t+1}\mid x_t,d_t)=\underbrace{p(x_{t+1}\mid x_t,d_t)}_{\text{状态转移}}\cdot\underbrace{g(\varepsilon_{t+1})}_{\text{i.i.d. taste shock}}$$

变量定义:$g(\cdot)$ 为 Type-I 极值密度。识别条件:(CI) 下未来 taste shock 与状态、选择独立,故可对 $\varepsilon'$ 解析积分(log-sum-exp);(S) 充分性假设 $x_t$ 总结了所有状态信息。二者缺一,Bellman 不可降维、CCP 无 logit 形式。经济直觉:CI 是"今天的选择不影响明天 taste shock 的分布",这是把动态问题压成静态 logit 递归的关键。

03 Bellman 方程与条件选择概率(CCP)

3.1 Bellman 方程

定义 $V(x, \varepsilon)$ 为在状态 $(x, \varepsilon)$ 下的期望最优值函数(ex ante value,即在知道 $\varepsilon$ 之前的价值):

Equation 3.1 — Bellman 方程(本页核心公式之一)
$$V(x, \varepsilon) = \max_{d \in \mathcal{D}} \left\{ u(x,d) + \varepsilon_d + \beta \, \mathbb{E}\left[ V(x', \varepsilon') \mid x, d \right] \right\}$$

展开来看,方括号里三项分别是:(1) 当期 flow utility $u(x,d)$;(2) 当期 taste shock $\varepsilon_d$;(3) 贴现后的未来期望价值。注意未来价值里的期望是对两个随机性取的:状态转移 $x' | x,d$ 与下一期 taste shock $\varepsilon'$。

3.2 Choice-specific value(不含 $\varepsilon$)

定义选择 $d$ 的"选择特定价值"(exclusive of $\varepsilon$):

Equation 3.2 — Choice-specific value
$$v(x,d; \theta) = u(x,d; \theta) + \beta \int \log \left( \sum_{d' \in \mathcal{D}} \exp v(x', d'; \theta) \right) p(x' | x, d) dx'$$

这是 Rust (1987) 的关键推导:由于 $\varepsilon_d$ 是 i.i.d. Type-I Extreme Value,对 $\varepsilon'$ 的积分有解析形式——log-sum-exp 表达式 $\log \sum_{d'} e^{v(x',d')}$。这把"对连续分布积分"简化成了一个封闭公式。

3.3 条件选择概率(CCP)

在状态 $x$ 下,决策者选择 $d$ 的概率(在 $\varepsilon$ 上积分后)是一个 logit 形式:

Equation 3.3 — Conditional Choice Probability (CCP)
$$P(d | x; \theta) = \frac{\exp v(x,d; \theta)}{\sum_{d' \in \mathcal{D}} \exp v(x, d'; \theta)}$$

这是 DDCM 的核心对象:CCP 把 structural 参数 $\theta$ 和数据中可观察的选择频率联系起来。给定参数 $\theta$,我们能算出在每个状态下每个选择被选中的概率;反过来,给定数据,我们能通过最大似然或矩估计反推 $\theta$。

04 Rust 模型:Bus Engine Replacement

Rust (1987 Econometrica) 的经典例子是 Madison Metropolitan Bus (MMB) 发动机更换问题

4.1 设定

  • 状态 $x$:bus 的里程(mileage),离散化为一个分箱变量(例如 $x \in \{0,1,\dots,174\}$ 表示每 5000 英里一档);
  • 选择 $d \in \{0, 1\}$:
    • $d=0$:继续使用(maintain),本期支付运行成本 $c(x)$;
    • $d=1$:更换发动机(replace),本期一次性支付成本 $RC$,里程重置为 0。
  • 当期效用(成本前加负号):
    • $u(x, 0) = -c(x) = -RC \cdot \theta_1 \cdot \log(1+x/\theta_2)$ (运行成本随里程上升);
    • $u(x, 1) = -RC$ (换新发动机的固定成本,里程归 0)。
  • 转移:选择 $d=0$ 时,里程按 Poisson 过程增加 0 或 1 档;选择 $d=1$ 时,里程重置为 0 并增加一期。
  • 贴现因子 $\beta$:通常校准为 0.95 或 0.99。

4.2 估计目标

待估参数 $\theta = \{\theta_1, \theta_2\}$(运行成本函数的斜率和曲率),有时还包括 $RC$(重置成本)。Rust 用最大似然估计:对每辆 bus 在每期的选择 $(x_t, d_t)$,似然贡献就是 $P(d_t | x_t; \theta)$,整个似然函数是这些 CCP 的乘积。

Equation 4.2b — Rust 完全似然(NFXP 目标,补全)
$$\ell(\theta)=\sum_{i=1}^{N}\sum_{t=1}^{T_i}\log P\big(d_{it}\mid x_{it};\theta\big),\qquad P(d_{it}\mid x_{it};\theta)=\frac{\exp v^*(x_{it},d_{it};\theta)}{\sum_{d'\in\mathcal{D}}\exp v^*(x_{it},d';\theta)}$$

变量定义:$v^*(x,d;\theta)$ 为给定 $\theta$ 时内层 Bellman 不动点解;$N$ 为 bus 数,$T_i$ 为第 $i$ 辆观测期数。识别条件:$\beta$ 不可与 flow utility 同时识别(Rust 1987 注明),须校准 $\beta$ 或加排除约束。经济直觉:这是"内层解 Bellman、外层优化似然"的嵌套目标,外层每次求梯度都要重新解内层不动点。

05 NFXP 算法:嵌套不动点

💡 基础知识库:本节用 NFXP(Bellman 不动点 + 外层似然优化)

NFXP 的"内层解 Bellman、外层优化参数"是经典嵌套结构,容易慢、不收敛。想了解如何用 MPEC 把 Bellman 方程改写成等式约束、与参数一次性联合求解?先学 基础知识库·MPEC →

Rust (1987) 提出的 NFXP (Nested Fixed Point, 嵌套不动点) 算法是 DDCM 估计的"标准解法"。结构是一个外层优化器 + 内层不动点求解。

Step 0: 准备
把状态空间 $\mathcal{X}$ 离散化为网格(如 $N_x = 175$ 个里程分箱),构造转移矩阵 $p(x'|x,d)$($N_x \times N_x$)。设定待估参数初值 $\theta^{(0)}$ 和贴现因子 $\beta$。
Step 1: 外层 — 给定 $\theta$,解 Bellman 不动点
对每个 $x$ 和 $d$,把 Equation 3.2 看作关于 $v(x,d)$ 的不动点方程:$v = T_\theta(v)$,其中 $T_\theta$ 是 Bellman 算子。用 value function iteration 或 policy function iteration 求 $v^*(\theta)$。
Step 2: 由 $v^*$ 计算 CCP
用 Equation 3.3 算 $P(d|x; \theta) = \exp v^*(x,d) / \sum_{d'} \exp v^*(x,d')$。
Step 3: 计算似然函数
对数据中每个观察 $(x_{it}, d_{it})$,构造 $\ell(\theta) = \sum_{i,t} \log P(d_{it} | x_{it}; \theta)$。
Step 4: 外层优化器更新 $\theta$
用 Newton / BFGS 等优化器根据 $\partial \ell / \partial \theta$ 提出新的 $\theta$,回到 Step 1。
Step 5: 收敛
外层优化器收敛,得到 $\hat\theta_{NFXP}$。报告参数估计、标准误(用 sandwich formula)和反事实模拟。

5.1 价值函数迭代(Value Function Iteration, VFI)细节

在内层不动点求解中,最常用的是 VFI:

Equation 5.1 — VFI 迭代
$$v^{(h+1)}(x,d) = u(x,d) + \beta \sum_{x'} p(x'|x,d) \log \sum_{d'} \exp v^{(h)}(x', d')$$

迭代直到 $\|v^{(h+1)} - v^{(h)}\|_\infty < 10^{-8}$。由于 Bellman 算子是压缩映射(压缩率 $\beta < 1$),VFI 保证收敛,但通常需要几百到几千次迭代。改进:Howard policy iteration 每 10-20 次 VFI 做一次 policy improvement,收敛快得多。

Equation 5.1b — Bellman 算子 $T_\theta$ 与压缩性质(补全)
$$(T_\theta v)(x,d)=u(x,d;\theta)+\beta\int\log\!\Big(\sum_{d'}e^{v(x',d')}\Big)p(dx'\mid x,d)$$ $$\|T_\theta v_1-T_\theta v_2\|_\infty\le\beta\,\|v_1-v_2\|_\infty,\qquad \beta\in(0,1)$$

变量定义:$T_\theta$ 为 Bellman 压缩算子。识别/收敛条件:$\beta<1$ 是压缩率的来源,Banach 不动点定理保证 $v^*$ 唯一且 VFI 几何收敛。经济直觉:$\beta$ 越小(越短视)收敛越快;这也是为什么动态结构模型把 $\beta$ 校准而非估计。

⚠ NFXP 的计算负担

当状态空间 $\mathcal{X}$ 很大(例如多维状态 $x = (mileage, age, wage)$,$N_x = 10^5$)时,内层 VFI 每次都要在 $N_x \times N_x$ 上做矩阵乘法,外层优化器又要调用内层几百次——总计算量爆炸。这就是 Hotz-Miller (1993) 出现的动机。

06 Hotz-Miller 方法:避免全解

💡 基础知识库:本节用 CCP 估计 + 一步 GMM/ML;似然不可得时改用 SMM

当动态模型含连续状态或均衡约束、似然写不出来时,可用模拟矩估计(SMM)匹配模拟矩。不熟悉?先学 基础知识库·非线性GMM/SMM →;想把 Bellman 约束一次性求解,见 基础知识库·MPEC →

6.1 核心思想

Hotz and Miller (1993 RES) 提出了一个两步法:不需要在每次外层迭代时都全解 Bellman 方程,而是先用非参数/半参数方法从数据中直接估计 CCP,再用 CCP 反推价值函数,最后做一步 GMM/ML

6.2 CCP 逆推公式(CCP inversion)

利用 log-sum-exp 的解析结构,Hotz-Miller 证明了一个关键恒等式:在 CCP $P(d|x)$ 和选择特定价值 $v(x,d)$ 之间存在一一对应关系。特别地,如果把"参考选择"(如 $d=0$)的价值设为 0 作归一化,那么:

Equation 6.1 — Hotz-Miller CCP 逆推(本页核心公式之二)
$$v(x,d) - v(x,0) = \log P(d | x) - \log P(0 | x)$$

推导:由 Equation 3.3,$P(d|x) = e^{v(x,d)} / \sum_{d'} e^{v(x,d')}$,于是 $\log P(d|x) = v(x,d) - \log \sum_{d'} e^{v(x,d')}$。两边对 $d=0$ 作差,log-sum-exp 项消掉,得到 Equation 6.1。

Equation 6.1b — Hotz-Miller 正向模拟值函数(补全)
$$\widehat{EV}(x;\hat\theta)=\hat v(x,0;\hat\theta)+\sum_{t=0}^{T}\beta^{t}\int\Big[\hat u(x_t,d_t;\hat\theta)+\log\sum_d e^{\hat v(x_t,d)}\Big]\,d\hat P(x_t\mid x;\hat\theta)$$

变量定义:$\hat P(x_t\mid x;\hat\theta)$ 为从数据估计的转移密度;$\hat v$ 由 Eq.6.1 从 $\hat P(d|x)$ 反推。识别条件:正向模拟用数据中的 $\hat P$ 替代 Bellman 迭代,故只需一步估计、无需内层不动点。经济直觉:HM 的精髓是"CCP 已包含最优策略的全部信息",从观测选择频率即可反推未来价值,这把 DDCM 从计算密集变成两步回归。

6.3 两步估计流程

Step A: 第一阶段 — 非参数估计 CCP
从数据中直接计算每个状态 $x$ 下选择 $d$ 的经验频率 $\hat P(d|x)$(kernel / sieve / 简单直方图)。这一步不依赖任何 structural 参数,纯数据驱动。
Step B: 由 $\hat P$ 反推 $\hat v$(Equation 6.1)
得到 $\hat v(x,d) - \hat v(x,0) = \log \hat P(d|x) - \log \hat P(0|x)$。
Step C: 第二阶段 — 估计 structural 参数 $\theta$
把反推出的 $\hat v$ 代回 Bellman 方程(Equation 3.2),构造 moments 或伪似然,对 $\theta$ 做 GMM/ML。这一步不需要再内层解 Bellman,因为 $\hat v$ 已经从数据里"借"来了。
Step D (可选): 迭代版 Hotz-Miller (Iccp)
用估计出的 $\hat\theta$ 重新解 Bellman,得到新的 CCP,再重新估计——如此迭代直到收敛(Aguirregabiria & Mira 2002 的 Nested Pseudo-Likelihood, NPL)。

6.4 优点与局限

  • 优点:计算量从"外循环 × 内层不动点"降到"一次非参数估计 + 一次低维优化",特别适合高维状态空间。
  • 局限:(a) 第一阶段需要数据在每个状态 $x$ 上都有足够多的观测—— curse of dimensionality;(b) 反事实分析需要重新解 Bellman,所以"估计快"不等于"反事实快";(c) 标准误需要考虑第一阶段非参数估计的不确定性(kernel bandwidth bias)。

07 完整 Python 实现(Rust 例子)

下面用 Rust (1987) 的 bus engine replacement 简化版本演示 NFXP 算法。我们实现:(1) 状态离散化;(2) Bellman 算子;(3) VFI;(4) MLE 外层优化。

python
"""
Rust (1987) Bus Engine Replacement —— NFXP 简化实现
====================================================
状态: x in {0, 1, ..., NX-1} 表示里程分箱
选择: d in {0,1} = {继续使用, 更换发动机}
当期效用:
    u(x, 0) = - theta1 * log(1 + x / theta2)   # 运行成本(负号表示成本)
    u(x, 1) = - RC                               # 重置成本(里程归 0)
转移:
    d=0: x' ~ Poisson(1) 加在 x 上(截断在 NX-1)
    d=1: x' = 0 + Poisson(1)
"""
import numpy as np
from scipy.optimize import minimize_scalar, minimize
from scipy.stats import poisson

# ---------- 1. 模型设定 ----------
NX = 90              # 状态数(里程分箱)
BETA = 0.95          # 贴现因子
RC = 11.7255         # 重置成本(校准值,Rust 论文里的量级)

# 真实参数(用于模拟数据)
theta1_true, theta2_true = 2.0, 10.0

# 状态向量
x = np.arange(NX)

# 转移概率矩阵 P[d] 是 (NX, NX): P[d][x, x_next] = Pr(x_next | x, d)
def build_transition(NX):
    P = [np.zeros((NX, NX)), np.zeros((NX, NX))]
    # 里程增加服从 Poisson(lambda=1)
    lam = 1.0
    k_max = 5
    pk = poisson.pmf(np.arange(k_max+1), lam)
    for xi in range(NX):
        for k in range(k_max+1):
            # d=0: 里程从 xi 增加 k
            xn0 = min(xi + k, NX - 1)
            P[0][xi, xn0] += pk[k]
            # d=1: 里程从 0 增加 k
            xn1 = min(k, NX - 1)
            P[1][xi, xn1] += pk[k]
    # 归一化(截断尾部)
    P[0] /= P[0].sum(axis=1, keepdims=True)
    P[1] /= P[1].sum(axis=1, keepdims=True)
    return P

P = build_transition(NX)

# ---------- 2. 当期效用 ----------
def flow_utility(theta1, theta2):
    """返回 (NX, 2) 的 flow utility 矩阵"""
    u0 = - theta1 * np.log(1 + x / theta2)   # 继续使用
    u1 = - RC * np.ones(NX)                   # 更换发动机
    return np.column_stack([u0, u1])

# ---------- 3. Bellman 算子 + VFI ----------
def bellman_operator(V, theta1, theta2):
    """
    V: (NX, 2) 上一期的 choice-specific value
    返回新的 V
    """
    u = flow_utility(theta1, theta2)   # (NX, 2)
    # ex-ante value: EV(x) = logsumexp over d of V(x, d)
    V_max = V.max(axis=1, keepdims=True)         # (NX, 1)
    EV = (V_max.squeeze(1) + np.log(np.exp(V - V_max).sum(axis=1)))  # (NX,)
    # 对每个 d: V_new(x, d) = u(x,d) + beta * sum_x' P[d][x,x'] * EV(x')
    V_new = np.zeros_like(V)
    for d in [0, 1]:
        EV_next = P[d] @ EV     # (NX,)
        V_new[:, d] = u[:, d] + BETA * EV_next
    return V_new

def solve_bellman(theta1, theta2, tol=1e-9, max_iter=5000):
    V = np.zeros((NX, 2))
    for it in range(max_iter):
        V_new = bellman_operator(V, theta1, theta2)
        diff = np.max(np.abs(V_new - V))
        V = V_new
        if diff < tol:
            break
    # 计算 CCP
    V_max = V.max(axis=1, keepdims=True)
    P_choice = np.exp(V - V_max) / np.exp(V - V_max).sum(axis=1, keepdims=True)
    return V, P_choice

# ---------- 4. 模拟数据 ----------
def simulate_data(P_choice, T=50, N=200, seed=0):
    """模拟 N 辆 bus 各 T 期的 (x_t, d_t)"""
    rng = np.random.default_rng(seed)
    data = []
    for i in range(N):
        xi = 0
        for t in range(T):
            # 根据 P_choice[xi, :] 抽 d
            d = rng.choice(2, p=P_choice[xi])
            data.append((xi, d))
            # 状态转移
            xn = rng.choice(NX, p=P[d][xi])
            xi = xn
    return np.array(data)

V_true, P_true = solve_bellman(theta1_true, theta2_true)
data = simulate_data(P_true, T=50, N=200)
print(f"模拟数据形状: {data.shape}")
print(f"更换率 (d=1 的比例): {data[:,1].mean():.3f}")

# ---------- 5. 似然函数 + MLE ----------
def neg_loglik(params, data):
    theta1, theta2 = params
    if theta2 <= 0:
        return 1e10
    try:
        V, P_choice = solve_bellman(theta1, theta2)
    except Exception:
        return 1e10
    # 似然: log P(d | x)
    x_obs = data[:, 0].astype(int)
    d_obs = data[:, 1].astype(int)
    p_obs = P_choice[x_obs, d_obs]
    p_obs = np.clip(p_obs, 1e-300, 1.0)
    nll = -np.sum(np.log(p_obs))
    return nll

# 外层优化
print("\n开始 MLE 估计 ...")
res = minimize(neg_loglik,
               x0=[1.0, 5.0],
               args=(data,),
               method='Nelder-Mead',
               options={'xatol':1e-4, 'fatol':1e-4, 'maxiter':50})
print(f"收敛: {res.message}")
print(f"估计 theta1 = {res.x[0]:.3f}  (真实 {theta1_true})")
print(f"估计 theta2 = {res.x[1]:.3f}  (真实 {theta2_true})")

# ---------- 6. 用估计参数画 CCP ----------
V_hat, P_hat = solve_bellman(*res.x)
print("\n更换概率 P(d=1 | x) 在不同里程分箱:")
for xi in [0, 10, 30, 50, 70, 89]:
    print(f"  x={xi:3d}  P(replace)={P_hat[xi,1]:.4f}")
✓ 代码说明

这段代码完整实现了 Rust (1987) 的 NFXP 算法:(1) 构造转移矩阵;(2) Bellman 算子 + VFI 解内层不动点;(3) 外层 Nelder-Mead 优化做 MLE。在普通笔记本上几秒内即可收敛。完整的学术论文级实现还需要:(a) 用真实 MMB 数据;(b) 标准误计算(analytic gradient);(c) 与 Hotz-Miller 两步法对比;(d) 反事实政策模拟(见下一页)。

07+ 数据来源对照表(动态结构模型常用数据集)

动态结构模型需要面板数据:同一个体/企业多期的状态 $x_t$ 与选择 $d_t$。下表对照经典与中国数据集:

数据集国家/地区典型动态选择状态变量获取
Rust MMB Bus美国是否更换公交车发动机累计里程、机龄Rust (1987) 原始数据(教学基准)
NLSY美国就业/职业/教育动态选择教育、经验、工资NLSY79 公网免费
PSID美国迁移、生育、劳动参与家庭资产、孩子数PSID 官网注册免费
CFPS中国教育、职业、退休动态家庭背景、收入、健康中国家庭追踪调查(北大)
CHARLS中国退休、健康、消费动态年龄、财富、健康中国健康与养老追踪调查
工商企业库中国企业进入/退出、投资资本、年龄、利润工业企业数据库(需申请)
动态结构数据的特殊要求

静态离散选择只要"一期横截面";动态结构必须有多期面板,且状态变量要能观察/可构造。Rust (1987) 的 MMB 公交车数据是教学基准(可公开下载);中国选题用 CFPS/CHARLS 做生命周期动态,或用工商企业库做企业投资/退出动态。

08 论文案例

English · Econometrica 1987
Optimal Replacement of GMC Bus Engines: An Empirical Model of Harold Zurcher
John Rust · Econometrica, 1987, 55(5): 999-1033
DDCM 的开山之作。用 Madison Metropolitan Bus 的发动机更换数据估计 bus 调度经理的"成本曲线"。提出了 NFXP 算法,把动态离散选择模型从理论变成了可计算的实证工具。是 IO、劳动、家庭经济学中所有后续动态结构模型的方法论源头。
English · Review of Economic Studies 1993
Estimation of Dynamic Discrete Choice Models Using Simulation
V. Joseph Hotz, Robert A. Miller · Review of Economic Studies, 1993, 60(3): 497-529
提出 CCP 逆推和两步估计法,把 DDCM 的计算复杂度从"内外双层不动点"降到"非参数第一阶段 + 低维第二阶段"。是高维状态空间 DDCM 实证应用的方法论基础。
English · Econometrica 1994
A Method of Simulated Moments for Estimation of Discrete Response Models Without Numerical Integration
Daniel McFadden · Econometrica, 1989(相关方法论); 以及 Keane & Wolpin (1994, JLE) 对动态劳动供给的应用
Keane and Wolpin (1994) 用动态结构模型估计女性教育、生育、劳动供给的联合决策。是 DDCM 在劳动经济学中的标杆应用,展示了如何在多维状态空间下用 simulation 方法估计复杂生命周期模型。
中文 · 经济研究
中国家庭生育决策与退休行为的动态结构估计
《经济研究》《经济学(季刊)》上关于中国生育政策、退休年龄改革、养老保险的结构估计论文
国内学者用 DDCM 框架估计中国家庭的生育、教育投资、退休决策。代表性研究讨论了:(1) 中国计划生育政策放松对生育行为的长期影响;(2) 延迟退休政策对劳动供给和养老金体系可持续性的反事实分析;(3) 用 CHIP/CFPS 微观面板数据作为状态变量和选择的来源。这些研究通常在 Rust (1987) 与 Hotz-Miller (1993) 框架上扩展,加入中国制度特征(如户籍、社保缴费规则)。
中文 · 世界经济
企业进入退出、出口沉没成本与动态结构模型
《世界经济》《数量经济技术经济研究》上关于中国企业出口行为、产业动态的结构估计论文
国内学者用 Ericson-Pakes (1995) 类型的动态产业模型估计中国制造业企业的进入、退出、出口决策。重点关注:(1) 出口沉没成本的大小;(2) 补贴政策对企业出口参与率的长期影响;(3) 国企改革对市场结构动态演化的作用。方法上常借鉴 Aguirregabiria & Mira (2010) 的 NPL 算法以缓解计算负担。

09 常见错误与陷阱

✗ 错误 1:忽略贴现因子 $\beta$ 的识别

很多学生把 $\beta$ 当自由参数估计,结果发现它和 flow utility 参数高度共线,似然曲面平坦,$\hat\beta$ 收敛到 0 或 1。实践中通常把 $\beta$ 校准为 0.95 或 0.99(对应年化 5% 或 1% 利率),不参与估计。Rust (1987) 原文也是这么做的。

✗ 错误 2:状态空间离散化过粗

把 bus 里程只分成 10 个 bins,看似节省计算,但 CCP 对状态的敏感性被平滑掉了,反事实政策分析完全失真。状态空间要细到"政策变化不会跨越 bin",通常 $N_x \geq 50$–$200$。

✗ 错误 3:把 taste shock 设成正态分布而非 Extreme Value

只有当 $\varepsilon_{d}$ 是 i.i.d. Type-I Extreme Value 时,log-sum-exp 公式才有解析形式,CCP 才是简单的 logit。如果改成正态分布(probit),内层不动点每次都要对多元正态数值积分,计算量爆炸。除非有特别理由,默认用 Extreme Value

⚠ 陷阱 4:Hotz-Miller 第一阶段在稀疏状态上做非参数估计

如果某些 $x$ 上数据很少(例如 bus 里程很高的罕见观测),$\hat P(d|x)$ 的方差极大,反推的 $\hat v$ 不可靠。需要做 smoothing(kernel / sieve)或合并相邻状态。

⚠ 陷阱 5:忽略未观察异质性

不同 bus 经理的"耐心"或"更换成本"可能是固定效应(fixed effect),如果忽略,CCP 估计会有偏。Rust 原文的早期版本就被 Heckman 等人批评过,后续文献用 mixed logit / finite mixture 处理。

10 进阶资料

方程总清单 / Equation Summary

本页全部方程按出现顺序汇总如下,共 10 个。每个方程均可在正文中找到对应的变量定义、设定理由与经济直觉。

编号方程名称核心公式所在节
Eq.05-01期望贴现效用(目标函数)$\max E[\sum_t\beta^t(u(x_t,d_t)+\varepsilon_{t,d_t})]$02.2
Eq.05-02Rust 条件独立假设(补全)$p(x',\varepsilon'\mid x,d)=p(x'\mid x,d)g(\varepsilon')$02.3(补全)
Eq.05-03Bellman 方程$V(x,\varepsilon)=\max_d\{u(x,d)+\varepsilon_d+\beta E[V(x',\varepsilon')\mid x,d]\}$03.1
Eq.05-04Choice-specific value$v(x,d)=u(x,d)+\beta\int\log\sum_{d'}e^{v(x',d')}p(x'\mid x,d)dx'$03.2
Eq.05-05CCP 条件选择概率$P(d\mid x;\theta)=e^{v(x,d)}/\sum_{d'}e^{v(x,d')}$03.3
Eq.05-06Rust 完全似然(补全)$\ell(\theta)=\sum_{i,t}\log P(d_{it}\mid x_{it};\theta)$04.2(补全)
Eq.05-07Bellman 算子 $T_\theta$ 与压缩(补全)$(T_\theta v)(x,d)=u+\beta\int\log\sum_{d'}e^{v(x',d')}p$;$\|T_\theta v_1-T_\theta v_2\|\le\beta\|v_1-v_2\|$05.1(补全)
Eq.05-08VFI 迭代$v^{h+1}(x,d)=u(x,d)+\beta\sum_{x'}p(x'\mid x,d)\log\sum_{d'}e^{v^h(x',d')}$05.1
Eq.05-09Hotz-Miller CCP 反转$v(x,d)-v(x,0)=\log P(d\mid x)-\log P(0\mid x)$06.2
Eq.05-10HM 正向模拟值函数(补全)$\widehat{EV}(x)=\hat v(x,0)+\sum_t\beta^t\int[\hat u+\log\sum_d e^{\hat v}]d\hat P$06.2(补全)