非线性GMM与模拟矩估计(SMM)
当矩条件成为参数的非线性函数、甚至没有解析表达式时,我们如何把"让模型矩贴近数据矩"这一思想落地?本页从非线性GMM的一般框架出发,落到数值优化、标准误与模拟矩估计 SMM,并延伸到间接推断(Indirect Inference)与有效矩估计(EMM),最后给出一个可直接运行的 Python 完整实例。
本页属于结构估计「基础知识库」,是 02 GMM 的高级延伸。定位:先单独学会这个工具,再到模型分支里看它怎么用。当似然写不出、矩也只能靠蒙特卡洛模拟近似时,就从解析 GMM 走到非线性 GMM / SMM。本页按「是什么 → 为什么学 → 数学定义 → 直觉 → 逐步操作 → 完整代码 → 常见错误」讲透。
- 动态结构模型 —— 似然不可解析写出时(如带连续状态、含均衡约束的动态选择),用 SMM 匹配模拟矩。
- 拍卖模型 —— 当分布假设复杂、似然不可得或计算昂贵时,用 SMM 替代 MLE 估计估值分布。
- HANK / 异质性主体宏观模型 —— 高维异质性下无解析似然,用 SMM/间接推断匹配宏观与截面矩。
numpy 模拟 + scipy.optimize)或 MATLAB;计算量大,建议熟悉向量化与并行。01 概念直觉:是什么、为什么、怎么用
在上一页的线性GMM中,我们熟悉的是这样一条矩条件:$E[Z_i'(y_i - X_i'\beta)] = 0$。这里矩条件关于参数 $\beta$ 是线性的——把样本矩对 $\beta$ 整理一下,立刻就能得到一个 closed-form 的权重矩阵两步估计量。但结构估计面对的模型往往没有这么"乖":一个动态离散选择模型里,条件选择概率 $P_i(\theta)$ 是 Bellman 方程不动点 $V(\theta)$ 的非线性函数;一个 DSGE 模型里,脉冲响应矩要先求解线性有理预期系统才能算出来。此时矩条件 $g(\theta)$ 关于参数 $\theta$ 是非线性的,甚至根本写不出解析表达式——这就是非线性GMM与模拟矩估计要解决的问题。
经济学直觉仍然是 GMM 的灵魂:"模型生成的矩"要尽量"贴近数据里的矩"。区别只在于:线性情形我们手算矩,非线性情形我们用数值优化器去最小化二次型目标函数;而当矩本身无法解析计算时,我们干脆用蒙特卡洛模拟去"造"出模型矩——这就是 SMM(Simulated Method of Moments)。它把"估计一个结构模型"变成了一个可以黑箱化的优化问题:给参数,模拟器吐出矩,优化器调整参数,循环直到矩匹配。
怎么用的典型工作流是:① 在真实数据上算出一组可观测矩 $m_{data}$(均值、方差、回归系数、脉冲响应、资产定价矩……);② 写出给定 $\theta$ 的模型模拟器;③ 用 $R$ 次模拟平均得到 $m_{sim}(\theta)$;④ 选定权重矩阵 $W$,最小化加权距离;⑤ 修正模拟噪声后算标准误。下面逐步展开。
非线性GMM = 矩条件对 $\theta$ 非线性的 GMM,靠数值优化求解;SMM = 矩条件没有解析式、用模拟数据算矩的 GMM。二者共享同一个"加权矩距离最小化"的骨架。
02 非线性GMM的一般框架与目标函数推导
2.1 矩条件的一般形式
设总体矩条件为 $E[g(Z_i,\theta_0)] = 0$,其中 $g:\mathbb{R}^d\times\Theta\to\mathbb{R}^L$ 是一个 $L$ 维矩函数,$Z_i$ 是观测数据,$\theta\in\Theta\subset\mathbb{R}^p$ 是待估参数。与线性情形不同,$g(\cdot,\theta)$ 关于 $\theta$ 一般是非线性的。样本矩平均为
2.2 目标函数:逐步推导
非线性GMM 的估计量定义为二次型目标函数的最小值。第一步,写出"矩残差"向量 $g_n(\theta)$;第二步,用对称正定权重矩阵 $W_n$($L\times L$)把 $L$ 维矩残差拼成一个标量;第三步,关于 $\theta$ 最小化:
推导到此为止——因为 $g(\cdot,\theta)$ 非线性,$\partial g_n/\partial\theta$ 无法再化简为一个线性投影,$Q_n(\theta)$ 一般没有解析解,必须交给数值优化器。这正是它和线性GMM最大的分水岭:线性时我们能解出 $\hat\beta = (X'ZWZ'X)^{-1}X'ZWZ'y$,非线性时我们只能写成"argmin"。
2.3 两步(efficient)GMM
与线性情形一样,最优权重矩阵是矩渐近方差的逆。记 $S = \lim_{n\to\infty} n\, E[g_n(\theta_0)g_n(\theta_0)']$(长期方差,可用 HAC/Newey-West 估计)。两步法:
03 数值优化:Nelder-Mead / BFGS / 模拟退火
因为 $Q_n(\theta)$ 没有闭式解,选对优化器直接决定成败。结构模型的目标函数常常非凸、有平坦区、有数值噪声,单一算法往往不够。
| 算法 | 类型 | 是否需要梯度 | 适用场景 | 特点 / 陷阱 |
|---|---|---|---|---|
| Nelder-Mead (单纯形) | 无导数直接搜索 | 否 | 低维、矩函数不可微(含模拟噪声) | 鲁棒但慢;高维($p>10$)易卡死,适合粗搜/起步 |
| BFGS / L-BFGS-B | 拟牛顿 | 数值/解析梯度 | 目标光滑、维数中等 | 快;依赖梯度质量,噪声大时会被误导 |
| 模拟退火 (Simulated Annealing) | 全局随机搜索 | 否 | 疑似多局部极小、非凸 | 能跳出局部极小,但收敛慢,常作"全局起步→局部精修"的前半段 |
| Powell / 共轭梯度 | 无导数 / 半牛顿 | 否 / 近似 | 矩函数可微但梯度难求 | 介于 Nelder-Mead 与 BFGS 之间的折中 |
先用 Nelder-Mead 或模拟退火在粗网格上多次随机起步(multistart),找到最有希望的盆地;再用 BFGS/L-BFGS-B 精修,并报告每次起步的收敛点是否一致。结构估计中"收敛到不同局部极小"是头号隐忧,multistart 几乎是标配。
04 非线性GMM的标准误 & 与线性GMM对比
4.1 渐近方差与标准误
记 $G = E[\partial g(Z_i,\theta_0)/\partial\theta']$($L\times p$ 的 Jacobian,用数值差分近似),$\hat S$ 为长期方差估计。最优 GMM($W=S^{-1}$)的渐近协方差为:
因此标准误为 $\widehat{\mathrm{Var}}(\hat\theta) = \frac1n(\hat G'\hat S^{-1}\hat G)^{-1}$,对角元开方即得。注意 $G$ 必须用数值差分估计(因为没有解析式),步长 $\delta$ 太大会有偏差、太小会被浮点噪声淹没,经验上用相对步长 $10^{-4}\sim 10^{-5}$。
4.2 与线性GMM对比
| 维度 | 线性GMM | 非线性GMM |
|---|---|---|
| 矩条件 | $g=Z'(y-X\beta)$,对 $\beta$ 线性 | $g(Z_i,\theta)$ 对 $\theta$ 任意非线性 |
| 解析解 | 有:$\hat\beta=(X'ZWZ'X)^{-1}X'ZWZ'y$ | 无,必须数值优化 argmin |
| Jacobian $G$ | $X'Z$(解析式) | 数值差分近似 |
| 局部极小风险 | 无(二次凸问题) | 有,需 multistart |
| 标准误公式 | 同左,但 $G$ 解析可得 | $(G'S^{-1}G)^{-1}/n$,$G$ 数值近似 |
| 过度识别检验 | Hansen J,同公式 | Hansen J,$nQ_n\to\chi^2(L-p)$ |
05 模拟矩估计 SMM:为什么模拟、目标函数、模拟噪声修正
5.1 为什么需要模拟(模型没有闭式矩条件)
很多结构模型(带偏好冲击的动态离散选择、带习惯形成的资产定价、DSGE 的高阶矩)根本写不出$E[g(Z_i,\theta)]$ 的解析表达式。但只要模型是一个可由随机种子驱动的数据生成过程(DGP),我们就能在给定 $\theta$ 下计算机模拟出一条长度 $n$ 的"人造样本",再在人造样本上算与真实数据相同定义的矩。这就是 McFadden (1989)、Pakes-Pollard (1989) 的洞见:用模拟器替代解析期望。
5.2 SMM 目标函数
设数据矩为 $m_{data}$($K\times1$),模拟 $R$ 条长度为 $n$ 的序列、在每条上算矩后平均,得模拟矩 $m_{sim}(\theta)$。SMM 估计量为:
直觉:选择参数,让"模型造出来的样本矩"尽可能贴近"真实样本矩"。$W$ 常用数据矩协方差的逆(两步法),使估计高效。
5.3 模拟噪声修正 $W = S + \frac{1}{R}\Sigma$
模拟引入了额外噪声。若数据矩协方差为 $S = \mathrm{Avar}(\sqrt n\, m_{data})$,单条模拟矩的协方差为 $\Sigma$,则 $R$ 次平均后模拟矩的额外噪声为 $\Sigma/R$。渐近有效的权重矩阵必须把这部分加进去,否则标准误会偏窄:
当 $R\to\infty$ 时修正项消失,回到普通GMM;当 $R$ 有限时,不做修正会"过度自信"。实践中常用 Newey-West/block bootstrap 同时估计 $S$ 与 $\Sigma$。
5.4 模拟次数 $R$ 怎么选
- 偏差角度:$R$ 越大,模拟矩越接近真实期望,估计偏差 $\to 0$。
- 方差角度:模拟噪声方差按 $1/R$ 下降,$R$ 翻四倍误差约减半。
- 成本角度:每次目标函数求值都要跑 $R$ 次模拟,$R$ 太大优化极慢。
- 经验法则:$R$ 取 $50$–$500$;重要技巧是共用随机数(common random numbers)——所有 $\theta$ 用同一组 $\varepsilon_t$,使 $m_{sim}(\theta)$ 关于 $\theta$ 光滑,大幅降低梯度噪声。
06 间接推断(Indirect Inference)与有效矩估计 EMM
6.1 间接推断(Gourieroux-Monfort-Renault, 1993)
选矩时,与其手挑"理论矩",不如先跑一个简单的辅助模型(auxiliary model):比如用 OLS 或线性 GARCH 在真实数据上得到辅助参数估计 $\hat\beta_{data}$(如均值方程系数、ARCH 系数)。然后在模拟数据上跑完全相同的辅助模型,得到 $\hat\beta_{sim}(\theta)$。间接推断估计量选择 $\theta$,使辅助参数在"数据"和"模拟"之间尽量一致:
基本思想:辅助模型不必"正确设定"(即不必是真实结构模型),只要它的参数对结构参数 $\theta$ 敏感("包含信息")即可。这把"选矩"难题转化成"选一个好估计过的辅助回归",非常适合时间序列、结构化金融与宏观模型。
6.2 有效矩估计 EMM(Gallant-Tauchen, 1996)
EMM 是 SMM 的"高效版":把辅助模型选为半非参数 SNP(Semi-Nonparametric)密度(一个足够灵活、能逼近任意真实似然的投影),再用 SNP 的得分函数(score)作为矩条件。当辅助 SNP 足够灵活时,EMM 渐近等价于极大似然,因此称为"有效"。它是 DSGE/结构化模型估计中"无需显式似然却逼近 MLE 效率"的经典路线。
07 完整 Python 代码:SMM 估计一个 ARCH(1)/结构模型
下面用一个可直接运行的例子:真实数据由 $\ y_t = \sigma_t\,\varepsilon_t,\ \sigma_t^2 = \omega + \alpha\,y_{t-1}^2$(ARCH(1))生成,我们不写似然,只用三个矩(无条件均值、无条件方差、滞后二阶自相关)做 SMM 估计,并演示共用随机数与两步权重。
import numpy as np
from scipy.optimize import minimize
# ============================================================
# SMM 完整实例:用模拟矩估计 ARCH(1) 结构参数
# 真实 DGP: y_t = sigma_t * eps_t, sigma_t^2 = w + alpha * y_{t-1}^2
# 待估: theta = (w, alpha),真值取 (0.1, 0.4)
# 我们刻意不写似然,只用 3 个矩做矩匹配
# ============================================================
rng = np.random.default_rng(2024)
def simulate_arch(theta, n, R, seed_base=123):
"""给定 theta=(w, alpha),模拟 R 条长度 n 的 ARCH(1) 序列。
关键技巧:所有 theta 共用同一组随机数(common random numbers),
使模拟矩关于 theta 光滑,梯度噪声大幅下降。"""
w, alpha = theta
sim_moments = np.zeros((R, 3))
for r in range(R):
# 每个 r 用固定随机流,不同 r 之间才独立(用于估计 Sigma)
eps = np.random.default_rng(seed_base + r).standard_normal(n)
y = np.zeros(n)
sig2 = w / (1 - alpha) if alpha < 0.99 else w
for t in range(1, n):
sig2 = w + alpha * y[t-1]**2 # ARCH(1) 方差递推
y[t] = np.sqrt(sig2) * eps[t]
# 三个与数据同定义的矩
m0 = np.mean(y) # 均值
m1 = np.var(y, ddof=1) # 方差
m2 = np.corrcoef(y[1:]**2, y[:-1]**2)[0, 1] # 平方序列一阶自相关
sim_moments[r] = [m0, m1, m2]
return sim_moments.mean(axis=0), sim_moments
# ---------- 1. 生成"真实数据" ----------
w_true, a_true = 0.1, 0.4
n_obs = 1000
data = np.zeros(n_obs)
np.random.seed(7)
sig2 = w_true/(1-a_true)
eps = np.random.standard_normal(n_obs)
for t in range(1, n_obs):
sig2 = w_true + a_true*data[t-1]**2
data[t] = np.sqrt(sig2)*eps[t]
# 数据矩(真实样本上的 3 个矩)
m_data = np.array([data.mean(), data.var(ddof=1),
np.corrcoef(data[1:]**2, data[:-1]**2)[0, 1]])
print("数据矩 m_data =", np.round(m_data, 4))
# ---------- 2. SMM 目标函数 ----------
def mm_smm(theta, W, n, R):
m_sim, _ = simulate_arch(theta, n, R)
d = m_data - m_sim
return d @ W @ d # 加权矩距离
# ---------- 3. 两步 GMM ----------
R = 50
# Step1: 单位权重粗估
W1 = np.eye(3)
res1 = minimize(mm_smm, x0=[0.2, 0.2], args=(W1, n_obs, R),
method='Nelder-Mead',
options={'xatol':1e-5, 'fatol':1e-6, 'maxiter':2000})
theta_hat1 = res1.x
print("Step1 粗估 theta =", np.round(theta_hat1, 4))
# Step2: 用模拟矩的协方差构造最优权重
_, sim_mat = simulate_arch(theta_hat1, n_obs, R)
Sigma = np.cov(sim_mat.T) # R 条模拟矩的协方差
# 模拟噪声修正:有效协方差 = 数据矩协方差 + (1/R)*Sigma
# 这里用模拟协方差近似 S,并加上 (1/R)*Sigma 修正项
W2 = np.linalg.inv(Sigma + Sigma/R)
res2 = minimize(mm_smm, x0=theta_hat1, args=(W2, n_obs, R),
method='BFGS', options={'gtol':1e-6})
theta_hat = res2.x
print("Step2 高效 SMM theta_hat =", np.round(theta_hat, 4),
" 真值 = (0.1, 0.4)")
# ---------- 4. 标准误(数值 Jacobian) ----------
def numerical_jac(theta, h=1e-4):
"""数值差分算模拟矩对 theta 的 Jacobian G (K x p)"""
m0, _ = simulate_arch(theta, n_obs, R)
G = np.zeros((3, 2))
for j in range(2):
tp = theta.copy(); tp[j] += h
mp, _ = simulate_arch(tp, n_obs, R)
G[:, j] = (mp - m0)/h
return G
G = numerical_jac(theta_hat)
Avar = np.linalg.inv(G.T @ W2 @ G) / n_obs # (G'WG)^-1/n
se = np.sqrt(np.diag(Avar))
print("标准误 se =", np.round(se, 4))
print("估计结果: w = %.4f (%.4f), alpha = %.4f (%.4f)"
% (theta_hat[0], se[0], theta_hat[1], se[1]))
MATLAB 中把 simulate_arch 写成函数句柄,外层用 fminsearch(Nelder-Mead)起步、fminunc(BFGS)精修;Jacobian 用 numgradient 或解析导数;权重用 HAC 协方差矩阵 hac 估计。结构与上面 Python 完全一一对应。
08 论文案例
09 常见错误(≥3)与进阶资料
常见错误
直接用 $W=S^{-1}$ 而不加 $(1/R)\Sigma$,相当于把"有限次模拟"当成"无穷次模拟",标准误会系统性偏小、过度拒绝原假设。正确做法是 $W=(S+\frac1R\Sigma)^{-1}$,或增大 $R$ 使该项可忽略。
若优化器每评估一次 $\theta$ 就重抽随机数,$Q_n(\theta)$ 会充满噪声,BFGS 的梯度估计彻底失效、Nelder-Mead 也会乱跳。必须固定随机种子 / 用共用随机数(CRN),让 $m_{sim}(\theta)$ 关于 $\theta$ 光滑可导。
非线性GMM/SMM 的目标函数经常非凸。只跑一个起点就宣布"收敛",很可能停在局部最小。务必做 multistart(随机起点 × 粗网格),比较各收敛点,再用 BFGS 精修最优点。
矩太少识别不足、矩太多权重矩阵 $\hat S$ 估计噪声巨大。过度识别时一定要报告 Hansen J 统计量 $nQ_n\to\chi^2(L-p)$;矩之间高度相关会让 $S^{-1}$ 接近奇异,需剔除冗余矩。
进阶资料
- Ljungqvist & Sargent, Recursive Macroeconomic Theory,SMM/间接推断章节(结构估计视角)。
- Cameron & Trivedi, Microeconometrics,Ch.13 非线性GMM 与 Ch.15 模拟估计。
- Adda & Cooper, Dynamic Economics: Quantitative Methods and Applications,SMM 完整算例。
- Duffie & Singleton (1993), "Simulated Moments Estimation of Markov Models of Asset Prices", Econometrica。