欢迎光临寒舍

结构估计──控制函数法

4961 字

一句话:控制函数法是升级版的工具变量法(IV)。

控制函数法(Control Function Method)完整深度讲解

第一部分:基础理论与直觉

1.1 问题的根源:内生性

什么是内生性?

在经济计量中,如果解释变量 X 是内生的,也就是跟残差不独立,$\operatorname{Cov}(X, \epsilon) \ne 0$,那么 OLS 有偏!

内生性在结构模型中的表现

在需求估计中,最常见的内生性来自价格

需求函数:$Q_i = α·P_i + X_i·β + ξ_i$

其中:

  • $Q_i$ = 销量(可观测)
  • $P_i$ = 价格(可观测)
  • $X_i$ = 产品特征(可观测)
  • $β$ = 价格效应(可观测)
  • $ξ _i$ = 产品质量/特征(不可观测)

问题: $ξ_i$与$P_i$相关!

为什么?因为企业的定价行为:

高质量产品($ξ_i$大) → 成本可能更高 或 需求更强 → 企业定更高的价格($P_i$大)

1
2
3
4
5
6
7
8
9
结果:Cov(P_i, ξ_i) > 0
      OLS高估了α的绝对值(负数更负)

经济学解释:
如果我们看到"价格高的产品卖得少",
这不仅是因为价格系数α < 0(需求曲线向下),
还因为高质量的产品(高ξ)本来就卖得多。
两个效应叠加,导致OLS对α的估计有偏。

1.2 传统解决方案的局限

工具变量法(IV)

思想: 找到与 $ξ_i$ 无关但与 $P_i$ 相关的工具变量 $Z_i$。

两阶段最小二乘(2SLS):

优点: ✓ 简单直观 ✓ 计算容易

缺点: ✗ 强外生性假设:Z 与 ε 完全无关 ✗ 弱工具变量问题 ✗ 多个内生变量时,需要同样多的工具变量 ✗ 无法处理"函数形式的内生性"

控制函数法的优势

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
相比IV,控制函数法:

1. 可以更灵活地处理内生性
   允许更复杂的内生变量结构

2. 可以进行半参数估计
   不需要指定完整的联合分布

3. 可以识别更丰富的异质性
   (例如:固定效应模型)

4. 与结构模型更自然融合
   特别是在产业组织问题中

代价:
需要更强的参数化假设
(虽然比看起来的弱)

1.3 控制函数的核心思想

一句话的精髓

1
2
3
如果你能估计内生变量中"坏的部分"(与误差相关的部分),
然后把它当作一个额外的解释变量加入模型,
就能"控制住"内生性!

直觉示例

你要研究教育对收入的影响

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
模型:Income_i = β₀ + β₁·Education_i + ε_i

问题:教育与ε相关
  为什么?因为能力(ability)既影响教育选择,也影响收入

标准IV的做法:
  找一个与能力无关但影响教育的工具(如父母教育)

控制函数的做法:
  1. 建立一个关于教育选择的模型:
     Education_i = f(Z_i) + v_i
     (Z是影响教育的变量,v是未解释部分)

  2. 估计这个模型,得到残差:
     v̂_i = Education_i - f(Z_i)

  3. 把v̂_i作为一个新的解释变量:
     Income_i = β₀ + β₁·Education_i + λ·v̂_i + ε_i

  4. 现在Education_i与(ε_i - λ·v̂_i)无关了!
     所以β₁可以通过OLS一致地估计。

关键洞察:
v̂_i代表了"教育中的能力相关部分"。
通过加入它,我们已经"控制"了能力。
剩下的教育变差,就是与能力无关的部分。

第二部分:方法的数学框架

2.1 标准的双变量情况

模型设定

考虑一个简单但很有代表性的模型:

需求方程(结构方程):

$$\boxed{ Y_i = α· \underbrace{X_i}_{内生} + β· \underbrace{Z_i}_{外生} + ε_i}$$

其中:

  • $Y_i ∈ ℝ$ 被解释变量
  • $X_i ∈ ℝ$ 内生解释变量(比如价格)
  • $Z_i ∈ ℝ^k$ 外生解释变量(产品特征)
  • $ε_i ∼ ?$ 结构误差(未观测质量)
  • $α, β ∈ ℝ$ 要估计的参数

第一阶段:模型化内生变量

因为 $X_i$ 是内生的,我们需要建立一个一阶段方程来描述 $X_i$ 的决定方式:

第一阶段方程:

$$X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i$$

其中:

  • $W_i ∈ ℝ^p$ 额外的外生变量(工具变量)
  • $v_i$ 第一阶段的误差
  • $γ₀, γ_Z, γ_W$ 参数

关键假设:

  1. $Z$外生
  2. $W$外生
  3. $W$与结构误差相关,这是为什么$W$能成为工具变量

关键的联系:结构误差与一阶段误差的关系

这是控制函数方法的核心

从第一阶段方程:

$$v_i = X_i - \gamma_0 - \gamma_Z·Z_i - \gamma_W \cdot W_i$$

关键假设:结构误差$ε_i$可以表示为一阶段误差$v_i$的函数:

$$ε_i = λ·v_i + η_i$$

其中:

  • $λ$ 系数(控制函数系数)
  • $\eta_i$ 新的误差项,满足 $E[η_i|Z_i, W_i, X_i] = 0$,或更强地 $E[η_i|Z_i, W_i, v_i] = 0$

经济学含义:

  • 结构误差(未观测产品质量)的一部分来自第一阶段中未被 $Z_i$, $W_i$ 解释的部分($v_i$)。
  • 剩下的部分 $η_i$ 是真正的随机冲击。

完整的系统

结构方程:

$$Y_i = α·X_i + β·Z_i + λ·v_i + η_i$$

一阶段:

$$X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i$$

合并第一阶段的定义:

$$Y_i = α·X_i + β·Z_i + λ·(X_i - γ₀ - γ_Z·Z_i - γ_W·W_i) + η_i$$

整理:

$$Y_i = (α + λ)·X_i + (β - λ·γ_Z)·Z_i - λ·γ₀ - λ·γ_W·W_i + η_i$$

2.2 推导与估计

三步估计程序(推荐的实施方法)

第一步:估计第一阶段

用 OLS 估计第一阶段方程:

1
2
3
4
5
6
7
8
  X_i = γ̂₀ + γ̂_Z·Z_i + γ̂_W·W_i + v̂_i

结果得到:
  - 参数估计:γ̂ = (γ̂₀, γ̂_Z, γ̂_W)'
  - 残差:v̂_i = X_i - γ̂₀ - γ̂_Z·Z_i - γ̂_W·W_i

为什么能用OLS?
因为Z_i和W_i都是外生的,所以OLS是一致的。

第二步:加入控制变量,估计结构方程

现在有了 $v̂_i$,把它当作一个新的解释变量:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
第二步回归:
  Y_i = α·X_i + β·Z_i + λ·v̂_i + η_i

用OLS估计。为什么有效?

理由:
1. X_i和Z_i可能与η_i相关,导致普通问题
2. 但v̂_i"吸收"了内生性来源
3. 一旦加入v̂_i,剩下的(η_i)就与X_i独立了

数学验证:
  E[X_i·η_i] = E[E[X_i·η_i|Z_i,W_i,v_i]]
             = E[X_i·E[η_i|Z_i,W_i,v_i]]    (条件期望性质)
             = E[X_i·0]                       (按假设)
             = 0

所以X_i与η_i确实无关,OLS有效!

第三步:渐近分布与推断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
OLS给出的估计量(α̂, β̂, λ̂)的渐近分布:

√n(θ̂ - θ₀) →^d N(0, Σ)

其中θ = (α, β, λ)',  Σ是渐近协方差矩阵。

关键:Σ不是标准OLS的协方差!

因为v̂_i是估计的(不是真实的),
所以我们需要进行"方差修正"。

标准方差修正(Newey-West, 1987):

Var̂(θ̂) = (X'X)^{-1} X'ÊÊ'X (X'X)^{-1}

其中Ê是残差矩阵,需要考虑到:
1. 残差 η̂_i = Y_i - α̂·X_i - β̂·Z_i - λ̂·v̂_i
2. v̂_i的估计误差贡献

一个具体的数值例子

假设我们有关于早餐麦片的数据:

1
2
3
4
5
6
7
8
9
变量定义:
- Y_i     = log(Sales_i)        销售量的对数
- X_i     = log(Price_i)        价格的对数
- Z_i     = [log(Sugar), Fiber] 产品特征
- W_i     = log(CornPrice_t)    玉米价格(工具变量)

理由:
玉米价格影响Kellogg产品的成本和定价,
但(理论上)不直接影响消费者需求。

第一步:估计第一阶段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
回归:log(Price_i) ~ log(CornPrice) + log(Sugar) + Fiber

假设估计结果:
  log(Price_i) = 2.5 + 0.4·log(CornPrice) + 0.3·log(Sugar) - 0.02·Fiber + v̂_i
                (0.2) (0.1)              (0.08)           (0.01)

R² = 0.65

解释:
- 玉米价格每上升1%,麦片价格上升0.4%
- 含糖量越高,价格越高
- 纤维含量越高,价格越低(健康产品溢价?)
- 模型解释了65%的价格变异

第二步:估计结构方程(加入控制函数)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
回归:log(Sales_i) ~ log(Price_i) + log(Sugar) + Fiber + v̂_i

结果:
  log(Sales_i) = 5.2 - 1.1·log(Price_i) + 0.3·log(Sugar) + 0.05·Fiber - 0.2·v̂_i
               (0.3) (0.2)             (0.1)            (0.02)          (0.1)

R² = 0.72

解释系数:
1. 价格系数 α̂ = -1.1
   解释:价格每上升1%,销量下降1.1%
   (合理的缺乏价格灵活性)

2. 控制函数系数 λ̂ = -0.2 (显著)
   解释:v_i显著非零!说明内生性确实存在。
   正面证据:控制函数方法是必要的。

3. v̂_i的t统计量 = -0.2/0.1 = -2.0
   说明在5%水平上显著。

4. 对比:如果直接OLS(不加v̂_i)

   OLS结果(错误的):log(Sales) ~ -0.8·log(Price) + ...
                     (0.3)

   OLS估计 α̂_OLS = -0.8 显著大于 -1.1
   偏差来源:不可观测的质量ξ_i与价格正相关
           高质量产品卖得多,但OLS把这归给"低价"
           导致高估了需求对价格的反应。

2.3 理论性质

为什么控制函数有效?

证明略,没人关心这玩意儿。

效率问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
问题:OLS对"第二步"回归给出有效的估计量吗?

不完全是!

理由:
1. v̂_i是估计的,不是真实的v_i
2. 这导致了"估计误差传递" (error-in-variables)
3. 方差比标准OLS会更大

解决方案:
使用修正的标准误(Newey-West, 1987

关键步骤:
1. 计算通常的OLS残差平方和
2. 加入v̂_i的估计误差贡献
3. 调整协方差矩阵

现代软件(Stata, R)通常有这个修正的内置选项,不用咱们操心。

第三部分:在产业组织中的应用

3.1 经典应用:产品差异化需求估计

问题设定

这是 Ackerberg 和 Caves (2003)的经典框架,广泛用于 IO 研究。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
背景:
估计产品需求时,产品质量ξ_j与价格P_j相关。

关键决策变量:
企业对产品的定价(古诺或Bertrand均衡)。

结果:
E[P_j, ξ_j] ≠ 0

例子(手机市场):
高质量手机(好摄像头、快处理器)→ 高价格
低质量手机(基础功能)→ 低价格

OLS会发生什么?

需求:ln(Sales_j) = α·ln(P_j) + X_j·β + ξ_j

OLS估计中:
Cov(ln(P_j), ξ_j) > 0
所以α̂_OLS会偏向零(比真实的α更不负)
→ 高估了价格缺乏弹性

控制函数方法的应用

第一步:建立产品选择模型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
企业j如何定价?根据成本和竞争环境:

定价方程(FOC):
  ln(P_j) = f(MC_j, 竞争强度, ξ_j) + u_j

简化形式:
  ln(P_j) = c₀ + c₁·ln(w_t) + c₂·X_j + c₃·ξ_j + u_j

其中:
- w_t = 工资或投入价格(工具变量)
- X_j = 产品特征(外生)
- ξ_j = 产品未观测质量(内生)
- u_j = 定价决策的随机性

问题:这个方程中ξ_j不可观测!

解决:使用"成本代理"方法

关键洞察:成本函数反演

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
从供给侧信息反演成本:

如果企业从事古诺竞争,一阶条件是:
  P_j - MC_j = -(Q_j / Σ_k (∂Q_k/∂P_j))

(这来自于边际收益=边际成本)

重新排列:
  MC_j = P_j + (Q_j / Σ_k (∂Q_k/∂P_j))

如果我们知道需求的价格导数(从需求估计),
我们可以反演出成本MC_j。

但这形成了一个循环:
- 需求依赖于ξ_j
- ξ_j影响定价
- 定价影响成本反演
- 成本反演影响ξ_j

控制函数打破这个循环!

第一步实施:定价方程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
策略1:使用投入价格作为工具变量

定价方程:
  ln(P_j) = c₀ + c₁·ln(w_t) + c₂·X_j + u_j

其中u_j包含了ξ_j的影响(是ξ_j的一个函数)。

估计这个方程,得到残差:
  û_j = ln(P_j) - ĉ₀ - ĉ₁·ln(w_t) - ĉ₂·X_j

这个û_j本质上是"质量的代理" (quality proxy)。

为什么?因为在定价方程中:
  ln(P_j) ≈ f(ξ_j) + ln(w_t) + ...

所以û_j ≈ ξ_j的未解释部分

策略2:使用需求导数

如果我们有需求的初步估计,可以计算:
  ∂Q_j/∂P_j (从需求函数)

然后反演边际成本。

但这需要谨慎,因为需求本身有估计误差。

第二步:加入控制函数的需求估计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
现在,需求方程加入û_j:

ln(Sales_j) = α·ln(P_j) + X_j·β + λ·û_j + η_j

用OLS估计。

参数解释:
- α: 价格弹性(现在一致地估计)
- β: 特征对需求的影响
- λ: 未观测质量的影响(应该为正)
- η_j: 真正的随机需求冲击

Ackerberg-Caves (2003)的原始框架

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
设定:
Y_jt = α·P_jt + X_j·β + ξ_j + ε_jt

其中ε_jt是"测量误差"或"需求冲击"。

特点:
ξ_j是"持久性"的未观测质量(跨时间相同)
ε_jt是"瞬间"的冲击(每期不同)

定价方程:
P_jt = g(ξ_j, w_t, X_j)

假设:
E[ε_jt | ξ_j, w_t, X_j] = 0

推导出:
P_jt与ξ_j相关(因为定价依赖于ξ_j)
但P_jt与ε_jt独立(短期冲击与长期特征无关)

这允许"某种形式的内生性"(关于ξ_j)
但不是"完全的"(ε_jt仍是外生的)。

控制函数:
用w_t反演ξ_j的值,然后加入需求方程。

3.2 另一个应用:企业生产函数估计

问题:中间投入的内生性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
生产函数:
Q_it = A_it · f(L_it, K_it, M_it)

其中:
- Q_it = 产出(可观测)
- L_it = 劳动(可观测)
- K_it = 资本(可观测)
- M_it = 中间投入,如材料(可观测)
- A_it = 企业的生产率 (未观测!)

问题:A_it与M_it相关!

为什么?
当企业知道自己的A_it很高时,
倾向于购买更多中间投入以提高产出。

结果:
Cov(M_it, A_it) > 0
→ OLS高估了M_it的系数
→ "过度估计材料投入的生产力"

Olley-Pakes (1996)的突破

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
解决方案:用企业的投资I_it反演生产率A_it

关键观察:
I_it = I_it(K_it, A_it)  (投资需求函数)

企业为什么投资?
当A_it高时(前景好),投资更多。
当需要替换资本时也投资。

所以,投资与生产率单调相关!

实施:
第一步:建立投资-生产率关系
        I_it = g(K_it, A_it)

        可以反演:A_it = g^{-1}(I_it, K_it)

第二步:用反演的Â_it代入生产函数
        Q_it = f(L_it, K_it, M_it) + Â_it

第三步:处理剩余的内生性
        (如L_it也可能与A_it相关)
        用其他工具变量

这是生产率分析中最著名的控制函数应用。

3.3 为什么控制函数在 IO 中特别有用?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
IO问题的特点:

1. 多个内生变量
   价格、产品特征、广告支出都可能内生
   → IV方法困难(需要太多工具变量)
   → 控制函数更灵活

2. 结构模型与制约条件
   企业的决策必须满足优化条件
   → 控制函数可以利用这些约束
   → 更有效的识别

3. 反事实分析的需要
   一旦估计了需求和成本,
   要模拟并购、价格变化等场景
   → 控制函数提供了清晰的"净"参数
   → 易于用于政策模拟

4. 异质性分析
   不同企业/产品有不同的边际成本
   → 控制函数可以识别这些异质性
   → IV方法会"平均"掉它们

第四部分:深度技术问题

4.1 方差修正(Variance Correction)

问题:为什么标准 OLS 标准误有问题?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
第二步回归:
  Y_i = α·X_i + β·Z_i + λ·v̂_i + η_i

如果我们用标准OLS公式计算标准误:

Var(θ̂) = σ̂²(X'X)^{-1}

这个公式是错的!

为什么?

假设σ̂² = (1/n)Ση̂_i²,其中η̂_i是残差。

但这个标准误会:
1. 忽视v̂_i中的估计误差
2. 高估精度(标准误太小)
3. t统计量和p值会有偏

结果:
我们倾向于高估显著性!

Newey (1984)和 Newey-West (1987)的修正

完整的方差修正程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
第一步:计算"影响函数" (influence function)

定义投影矩阵:
  H_i^{(1)} = ∂/∂v_i (第一阶段的预测)
            = -[γ̂_Z·∂Z_i/∂v_i + γ̂_W·∂W_i/∂v_i]

简化情况下(线性第一阶段):
  H_i^{(1)} = -X_i(因为v_i进入X_i)

第二步:估计"修正方差"

标准OLS方差:
  Var̂(θ̂) = (1/n)Σ(Y_i - Ŷ_i)²·(X_i, Z_i, v̂_i)'(X_i, Z_i, v̂_i)·...^{-1}

修正方差:
  Var̂_corrected(θ̂) = (1/n)Σ(Y_i - Ŷ_i)²·(W_i^*)'(W_i^*) · ... ^{-1}

其中W_i^* = (X_i, Z_i, v̂_i - H_i^{(1)})

最后一项v̂_i - H_i^{(1)}反映了估计的v̂_i的不确定性。

第三步:计算修正的标准误

SE̅_corrected = √Var̂_corrected / √n

实际实施

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
在Stata中:

步骤1:第一阶段回归
  reg X Z W
  predict vhat, residuals

步骤2:第二步回归,带方差调整
  reg Y X Z vhat, robust

  (robust选项会自动进行某种形式的调整)

但更准确的做法是使用特殊命令:

  // 如果使用Newey方法
  newey Y X Z vhat, lag(0)

或者,手动进行完整的修正:

步骤1:第一阶段
  reg X Z W
  scalar rss1 = e(rss)
  predict vhat, residuals
  gen grad_v = -X  // 偏导数

步骤2:第二步,保存残差
  reg Y X Z vhat
  predict eta_hat, residuals

步骤3:计算修正的协方差

  // 这需要矩阵代数
  // 可以用matrix commands或Mata

何时方差修正很重要?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
如果:

1. v̂_i的估计不精确(第一阶段R²较低)
   → 方差修正很重要

2. v̂_i的预测能力强(高R²)
   → 修正较小

3. λ较大(控制函数系数大)
   → 修正较大

4. 样本量很小
   → 修正相对重要

经验法则:
当第一阶段R² < 0.7时,报告修正后的标准误
否则,修正和不修正的标准误差异不大

4.2 识别条件

什么时候控制函数"有效"?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
关键条件1:排除约束 (Exclusion Restriction)

第一阶段:X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i
结构方程:Y_i = α·X_i + β·Z_i + λ·v_i + η_i

条件:W_i出现在第一阶段但不出现在结构方程
      (W_i不直接进入Y_i)

这就是标准的"排除约束",与IV相同。

关键条件2:功能形式假设

假设:ε_i = λ·v_i + η_i

这意味着结构误差与一阶段误差的关系是线性的。

如果真实关系是非线性的(比如ε_i = λ·v_i² + η_i),
那么模型是错误指定的。

检验方法:
add v_i², v_i³等高阶项
看系数是否显著

秩条件与过度识别

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
识别的秩条件:

给定第一阶段:
  X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i

要估计的参数:(α, β, λ)

识别需要:
- 至少一个W变量(来自p > k,即工具多于内生变量)
- W与X有"足够的"相关性(相关性秩条件)

过度识别检验:

如果p > 1(多于一个工具变量),
可以进行Sargan检验(或其他过度识别检验):

H0: 所有工具变量都是有效的(都与η_i无关)

检验统计量:
J = n·ĝ'Ŵ^{-1}ĝ ~ χ²_{p-1}

其中:
ĝ = 第一步残差与工具变量的协方差
Ŵ = 工具变量的协方差矩阵

如果J很大(p值小),拒绝H0
→ 至少一个工具变量是内生的
→ 需要重新考虑工具变量

4.3 常见陷阱与解决方案

陷阱 1:参数的因果解释

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
常见错误:
"控制函数系数λ̂ = -0.2意味着
未观测质量每单位提高,销量下降0.2%"

为什么这是错的?

λ̂估计的是什么?
λ̂是ε与v的关系系数。

结构方程:Y = α·X + β·Z + λ·v + η

这里,v是第一阶段的残差(不可观测)。

λ的含义:
"第一阶段中,未被Z和W解释的X的部分"
与"结构误差"的相关程度。

这不是"未观测质量"的直接系数。

要得到未观测质量的"真实"效应,
需要额外的识别假设。

正确解释:
λ̂显著≠0说明存在内生性
(我们的控制确实有必要)
但λ̂本身的大小没有直接经济学含义。

陷阱 2:多个内生变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
假设有两个内生变量:

Y_i = α_1·X_{1i} + α_2·X_{2i} + β·Z_i + ε_i

其中X_1和X_2都是内生的。

两个第一阶段方程:
  X_{1i} = γ_{10} + γ_{1Z}·Z_i + γ_{1W1}·W_{1i} + γ_{1W2}·W_{2i} + v_{1i}
  X_{2i} = γ_{20} + γ_{2Z}·Z_i + γ_{2W1}·W_{1i} + γ_{2W2}·W_{2i} + v_{2i}

关键问题:
v_{1i}和v_{2i}可能相关!

Cov(v_{1i}, v_{2i}) ≠ 0可能成立

这会导致什么?

如果我们同时加入v̂_{1i}和v̂_{2i}为控制:

Y_i = α_1·X_{1i} + α_2·X_{2i} + β·Z_i + λ_1·v̂_{1i} + λ_2·v̂_{2i} + η_i

那么,即使v̂_{1i}和v̂_{2i}有共线性,
OLS仍然是无偏的(只要η_i与所有变量独立)。

但是:
如果v̂_{1i}和v̂_{2i}高度共线,
估计会变得不稳定,标准误会很大。

解决:
检查v̂的相关性矩阵
如果高度共线,考虑使用岭回归或其他正则化方法
或者重新考虑模型规范

陷阱 3:动态模型中的控制函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
假设模型是动态的:

Y_{it} = α·Y_{it-1} + β·X_{it} + λ·v_t + η_{it}

其中v_t是第一阶段的残差。

问题:
Y_{it-1}很可能与η_{it}相关!
(如果η有持久性)

这违反了控制函数方法的基本假设。

解决方案:
1. 使用动态面板方法(Arellano-Bond)
2. 或者对控制函数进行更复杂的修改
3. 或者完全改用其他方法(GMM)

第五部分:与其他方法的对比

5.1 控制函数法 vs. 工具变量法

详细对比表

特征 控制函数 工具变量(2SLS)
理论基础 条件期望 $E[\varepsilon \mid Z,W,v]$ 正交性 $E[\varepsilon Z, W]=0$
多内生变量 ✓ 灵活 ✓ 但需求等量工具
异质性 ✓ 可识别差异化效应 ✗ 仅"平均"效应
计算 ✓ 两个 OLS + 简单 ✓ 矩阵运算
统计推断 需要方差修正 标准(有现成公式)
弱工具变量 部分抗性 ✗ 严重问题
模型规范错误 ✗ 对函数形式敏感 ✓ 相对稳健
小样本性质 未知(理论困难) 已知(有渐近理论)

何时选择哪一个?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
使用控制函数当:

1. 多个内生变量
   (相对工具变量方法更简洁)

2. 有结构模型可利用
   (例如:已知内生变量的决策函数)

3. 需要识别异质效应
   (例如:不同企业对价格的不同敏感度)

4. 有足够好的代理变量
   (可以很好地解释内生变量)

使用工具变量当:

1. 难以指定结构模型
   (只是想找到某个因果关系)

2. 有明确的排除约束
   (工具变量清晰可得)

3. 样本量很小
   (控制函数的小样本性质未知)

4. 关心稳健性
   (不想依赖特定的函数形式)

5.2 控制函数法 vs. GMM

区别在哪?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
GMM(广义矩方法):

使用多个矩条件:
  E[h(X_i, Y_i, θ)] = 0

例如:
  E[(Y_i - α·X_i - β·Z_i)·W_i] = 0
  (工具变量矩条件)

特点:
✓ 非常通用
✓ 可以处理任意数量的矩条件
✓ 有一致的渐近理论
✗ 计算复杂(需要最小化一个目标函数)
✗ 小样本性质可能较差

控制函数:

特点:
✓ 两步,计算简单(只要会做OLS)
✓ 清晰的经济直觉
✗ 依赖于特定的函数形式假设
✗ 需要手工进行方差修正

关系:
控制函数可以看作是GMM的一个特例
(使用了特定的矩条件结构)

什么时候两者给出相同结果?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
在某些特殊情况下,控制函数和GMM是等价的:

条件:
1. 线性模型
2. 线性第一阶段
3. 正态分布假设
4. 完全指定的矩条件

在这些条件下:
CF的参数估计 ≈ IV/GMM的参数估计

但标准误可能不同
(如果使用了不同的方差修正)

一般地,对于非线性模型:
CF和GMM可能给出不同的估计量
(即使都是一致的)

选择哪一个?
如果有现成的CF框架,用CF(更快)
否则,用GMM(更通用)

5.3 控制函数法 vs. Hausman 方法

Hausman 方法是什么?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
思想(Hausman, 1978):

如果能比较:
1. OLS估计(有偏但可能有效)
2. IV估计(无偏但可能无效)

差异大小可以告诉我们内生性有多严重。

Hausman检验:

H_0: OLS和IV估计相同
    (即,没有内生性)

检验统计量:
Z = (β̂_IV - β̂_OLS)' Var̂(β̂_IV - β̂_OLS)^{-1} (β̂_IV - β̂_OLS)

渐近分布:
Z ~ χ²_k

优点:
✓ 不需要指定第一阶段模型
✓ 检验内生性是否实际存在

缺点:
✗ 只是一个检验,不能"修正"内生性
✗ 如果拒绝H_0,你仍然需要选择用哪个估计
✗ 在弱工具变量下性质很差

与控制函数的关系:
控制函数可以看作是"更直接的"解决方案
(而非只是检验内生性)

第六部分:实施指南与代码

6.1 Stata 实现

完整的例子:麦片市场需求估计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
* ============================================
* 控制函数法:麦片市场需求估计
* ============================================

use cereal.dta, clear

* 变量定义:
* lnsales: log(销售量)
* lnprice: log(价格)
* sugar: 糖含量
* fiber: 纤维含量
* cornprice: 玉米价格(工具变量)

* ============================================
* 第一步:估计定价方程(第一阶段)
* ============================================

reg lnprice cornprice sugar fiber, robust

* 保存参数用于后续计算
local gamma0 = _b[_cons]
local gamma1 = _b[cornprice]
local gamma2 = _b[sugar]
local gamma3 = _b[fiber]

* 计算残差(控制函数)
predict v_hat, residuals

* 显示第一阶段结果
display "第一阶段回归结果:"
display "R² = " e(r2)
correlate lnprice cornprice  // 检查工具变量的相关性

* ============================================
* 第二步:估计需求方程(加入控制函数)
* ============================================

reg lnsales lnprice sugar fiber v_hat, robust

* 保存结果
estimates store CF_results

* ============================================
* 方差修正(手动)
* ============================================

* 方法1:使用Newey命令(自动进行某些修正)
newey lnsales lnprice sugar fiber v_hat, lag(0)

* 方法2:Bootstrap修正(更稳健)
bootstrap, reps(500) seed(12345): ///
  reg lnsales lnprice sugar fiber v_hat

* ============================================
* 对比OLS(有偏的估计)
* ============================================

reg lnsales lnprice sugar fiber, robust
estimates store OLS_results

* 显示两种估计的对比
estimates table CF_results OLS_results, ///
  b(%9.4f) se(%9.4f) title("OLS vs 控制函数法")

* ============================================
* 经济学检验
* ============================================

* 检验控制函数系数是否显著
test v_hat = 0  // 测试内生性是否存在

* 显示价格弹性
margins, dydx(lnprice)  // 边际效应

* ============================================
* 敏感性检查
* ============================================

* 添加高阶项,检查函数形式
gen v_hat2 = v_hat^2
reg lnsales lnprice sugar fiber v_hat v_hat2, robust
test v_hat2 = 0  // v_hat的非线性项是否显著?

更复杂的例子:处理多个内生变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
* 假设price和advertising都是内生的

* ============================================
* 第一阶段(两个方程)
* ============================================

* 第一阶段1:价格方程
reg lnprice cornprice prodcost sugar fiber, robust
predict v1_hat, residuals

* 第一阶段2:广告方程
reg advertising cornprice budget sugar fiber, robust
predict v2_hat, residuals

* ============================================
* 第二步:需求方程(双控制函数)
* ============================================

reg lnsales lnprice advertising sugar fiber v1_hat v2_hat, robust

* 检验两个控制函数是否都显著
test v1_hat = 0  v2_hat = 0

* 显示相关性(诊断检查)
correlate v1_hat v2_hat  // 两个控制函数的相关性
                          // 如果太高,可能有共线性问题

6.2 R 语言实现

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# ============================================
# 控制函数法的R实现
# ============================================

library(tidyverse)
library(lmtest)
library(sandwich)

# 读取数据
data <- read.csv("cereal.csv")

# ============================================
# 第一步:第一阶段回归
# ============================================

stage1 <- lm(log(price) ~ log(cornprice) + sugar + fiber, data = data)

# 提取残差(控制函数)
data$v_hat <- residuals(stage1)

# 显示第一阶段
summary(stage1)

# ============================================
# 第二步:第二阶段回归(加入控制函数)
# ============================================

stage2 <- lm(log(sales) ~ log(price) + sugar + fiber + v_hat, data = data)

# 标准结果
summary(stage2)

# ============================================
# 稳健标准误(修正内生性导致的偏差)
# ============================================

# 方法1:HC3稳健标准误
coeftest(stage2, vcov = vcovHC(stage2, type = "HC3"))

# 方法2:Bootstrap标准误
library(boot)

cf_regression <- function(data, indices) {
  d <- data[indices, ]

  # 第一阶段
  stage1 <- lm(log(price) ~ log(cornprice) + sugar + fiber, data = d)
  d$v_hat <- residuals(stage1)

  # 第二阶段
  stage2 <- lm(log(sales) ~ log(price) + sugar + fiber + v_hat, data = d)

  return(coef(stage2))
}

boot_results <- boot(data = data,
                     statistic = cf_regression,
                     R = 1000)

# 显示Bootstrap结果
boot_results

# ============================================
# 对比OLS(有偏)
# ============================================

ols_naive <- lm(log(sales) ~ log(price) + sugar + fiber, data = data)

# 创建对比表
comparison <- data.frame(
  OLS = coef(ols_naive),
  CF = coef(stage2)
)

print(comparison)

# ============================================
# 高级:自定义控制函数方法类
# ============================================

control_function_estimator <- function(
    struct_formula,   # 结构方程公式
    stage1_formula,   # 第一阶段公式
    data,
    method = "OLS"
) {

  # 第一阶段
  stage1_mod <- lm(stage1_formula, data = data)
  data$v_hat <- residuals(stage1_mod)

  # 更新结构公式,加入控制函数
  struct_formula_updated <- update(struct_formula, . ~ . + v_hat)

  # 第二阶段
  if (method == "OLS") {
    stage2_mod <- lm(struct_formula_updated, data = data)
  } else if (method == "robust") {
    stage2_mod <- lm(struct_formula_updated, data = data)
    # 使用稳健标准误
    se <- sqrt(diag(vcovHC(stage2_mod, type = "HC1")))
  }

  return(list(
    stage1 = stage1_mod,
    stage2 = stage2_mod,
    se_robust = se
  ))
}

# 使用自定义函数
result <- control_function_estimator(
  struct_formula = log(sales) ~ log(price) + sugar + fiber,
  stage1_formula = log(price) ~ log(cornprice) + sugar + fiber,
  data = data,
  method = "robust"
)

summary(result$stage2)

6.3 Python 实现

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import numpy as np
import pandas as pd
import statsmodels.api as sm
from scipy import stats

# ============================================
# 控制函数法的Python实现
# ============================================

# 读取数据
data = pd.read_csv("cereal.csv")

# ============================================
# 第一步:第一阶段回归
# ============================================

# 准备变量
X_stage1 = data[['cornprice', 'sugar', 'fiber']]
X_stage1 = sm.add_constant(X_stage1)
y_stage1 = np.log(data['price'])

# 运行第一阶段
stage1_model = sm.OLS(y_stage1, X_stage1).fit()

print("第一阶段回归结果:")
print(stage1_model.summary())

# 提取残差(控制函数)
v_hat = stage1_model.resid
data['v_hat'] = v_hat

# ============================================
# 第二步:第二阶段回归
# ============================================

X_stage2 = data[['log_price', 'sugar', 'fiber', 'v_hat']]
X_stage2 = sm.add_constant(X_stage2)
y_stage2 = np.log(data['sales'])

stage2_model = sm.OLS(y_stage2, X_stage2).fit()

print("\n第二阶段回归结果:")
print(stage2_model.summary())

# ============================================
# 方差修正(完整的方法)
# ============================================

def compute_cf_vcov(stage1, stage2, data):
    """
    计算控制函数估计的修正方差矩阵
    """
    n = len(data)
    k = stage2.params.shape[0]

    # 获取残差
    residuals = stage2.resid

    # 获取第二阶段的X矩阵
    X2 = np.column_stack([np.ones(n),
                          np.log(data['price']),
                          data['sugar'],
                          data['fiber'],
                          data['v_hat']])

    # 第一阶段的X矩阵
    X1 = np.column_stack([np.ones(n),
                          np.log(data['cornprice']),
                          data['sugar'],
                          data['fiber']])

    # 计算投影矩阵
    P1 = X1 @ np.linalg.inv(X1.T @ X1) @ X1.T

    # 调整后的X矩阵(考虑到v_hat的估计误差)
    X2_adj = np.copy(X2)
    X2_adj[:, -1] = (np.eye(n) - P1) @ data['v_hat'].values

    # 计算修正的方差
    XtX_inv = np.linalg.inv(X2.T @ X2)
    meat = X2_adj.T @ np.diag(residuals**2) @ X2_adj
    vcov = XtX_inv @ meat @ XtX_inv

    return vcov

# 计算修正的标准误
vcov_cf = compute_cf_vcov(stage1_model, stage2_model, data)
se_cf = np.sqrt(np.diag(vcov_cf))

# 显示修正的结果
print("\n修正后的标准误:")
for i, name in enumerate(stage2_model.params.index):
    t_stat = stage2_model.params[i] / se_cf[i]
    p_value = 2 * (1 - stats.t.cdf(np.abs(t_stat), n - k))
    print(f"{name}: {stage2_model.params[i]:.4f} ({se_cf[i]:.4f}) [t={t_stat:.3f}, p={p_value:.4f}]")

# ============================================
# 对比OLS(有偏的估计)
# ============================================

X_ols = data[['log_price', 'sugar', 'fiber']]
X_ols = sm.add_constant(X_ols)
ols_model = sm.OLS(y_stage2, X_ols).fit()

print("\nOLS vs 控制函数法对比:")
comparison = pd.DataFrame({
    'OLS': ols_model.params,
    'CF': stage2_model.params,
    'Difference': stage2_model.params - ols_model.params
})
print(comparison)

# ============================================
# 经济学检验
# ============================================

# 1. Hausman检验:OLS和CF估计是否显著不同?
hausman_stat = (stage2_model.params - ols_model.params).T @ \
               np.linalg.inv(vcov_cf - ols_model.cov_params()) @ \
               (stage2_model.params - ols_model.params)
p_value_hausman = 1 - stats.chi2.cdf(hausman_stat, df=len(stage2_model.params))

print(f"\nHausman检验(CF vs OLS):")
print(f"Test stat = {hausman_stat:.4f}, p-value = {p_value_hausman:.4f}")

# 2. 测试控制函数系数是否显著
lambda_coef = stage2_model.params['v_hat']
lambda_se = se_cf[-1]
t_stat = lambda_coef / lambda_se
p_value = 2 * (1 - stats.t.cdf(np.abs(t_stat), n - k))

print(f"\n控制函数系数检验:")
print(f"系数 = {lambda_coef:.4f}")
print(f"标准误 = {lambda_se:.4f}")
print(f"t统计量 = {t_stat:.3f}")
print(f"p-value = {p_value:.4f}")

if p_value < 0.05:
    print("→ 控制函数显著!内生性确实存在。")
else:
    print("→ 控制函数不显著。可能没有内生性,或者模型规范有问题。")

# ============================================
# 敏感性分析:添加高阶项
# ============================================

data['v_hat_sq'] = data['v_hat']**2

X_stage2_ext = data[['log_price', 'sugar', 'fiber', 'v_hat', 'v_hat_sq']]
X_stage2_ext = sm.add_constant(X_stage2_ext)

stage2_extended = sm.OLS(y_stage2, X_stage2_ext).fit()

print("\n带高阶项的模型:")
print(stage2_extended.summary())

# F检验:高阶项是否显著?
f_stat = stage2_extended.f_tests([[0, 0, 0, 0, 0, 1]]).statistic[0][0]
p_value = 1 - stats.f.cdf(f_stat, 1, n - k - 1)

print(f"\nv_hat²的F检验:p-value = {p_value:.4f}")
if p_value < 0.05:
    print("→ 非线性关系显著。考虑使用扩展模型。")
else:
    print("→ 线性假设合理。")

第七部分:常见问题与疑惑解答

7.1 理论问题

Q1: 为什么一定要把$v_i$加入第二步回归?直接用第一阶段的预测值$\hat{X}_i$不行吗?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
A: 这个问题很好!让我澄清区别。

方法1(你的想法):
第一阶段:X̂_i = γ̂₀ + γ̂_Z·Z_i + γ̂_W·W_i
第二阶段:Y_i = α·X̂_i + β·Z_i + ε_i

这其实就是标准的IV/2SLS方法!

方法2(控制函数):
第一阶段同上,再算残差 v̂_i = X_i - X̂_i
第二阶段:Y_i = α·X_i + β·Z_i + λ·v̂_i + η_i

区别在哪?

在方法1中,我们用X̂替代了X,
但这会改变回归的结构。

在方法2中,我们保留原始的X,
只是加入了一个额外的控制变量。

结果:
在线性模型中,两种方法给出相同的参数估计!
(对于同一个目标参数α)

但:
1. 标准误计算不同
2. 在非线性模型中,两种方法给出不同结果
3. 控制函数在结构模型中更容易应用

所以,哪种方法更好取决于具体情况。

Q2: 为什么假设$E[\varepsilon_i | Z_i, W_i, v_i] = 0$?这与排除约束是什么关系?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
A: 这是理解控制函数的关键。

排除约束(用于IV):
E[ε_i | Z_i, W_i] = 0

含义:W_i与ε_i无关
(这是标准的工具变量外生性假设)

控制函数的假设:
E[ε_i | Z_i, W_i, v_i] = 0

含义:给定了v_i后,W_i与ε_i的关系被消除了

区别:
排除约束说 W_i根本就不与ε_i相关
控制函数假设说 W_i的影响可以通过v_i被解释

哪一个更强?

两者都很强!但形式不同。

排除约束:无条件的独立性
控制函数:条件的独立性(给定v_i)

在实践中,哪一个更可信?

通常,控制函数的假设更容易满足,
因为v_i"吸收"了W_i的一部分效应。

例子:
W_i = 投入价格(如钢铁价格)
ε_i = 未观测的产品质量

排除约束说:钢铁价格与产品质量完全无关
→ 很强!钢铁价格影响定价,定价与质量相关

控制函数说:给定了定价残差后,
钢铁价格与质量无关
→ 更合理!定价已经是给定的,就没有额外的质量影响

所以,排除约束实际上隐含在v_i的定义中。

Q3: 如果第一阶段是非线性的怎么办?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
A: 好问题!这涉及到Ackerberg-Caves (2003)的推广。

假设第一阶段是非线性的:
X_i = g(Z_i, W_i; γ) + v_i

例如:
X_i = exp(γ_Z·Z_i + γ_W·W_i) + v_i
X_i = (γ_Z·Z_i)^{1/γ_W} + v_i

怎么处理?

第一步:估计非线性第一阶段
使用非线性最小二乘(NLS)或最大似然

第二步:计算残差
v̂_i = X_i - ĝ(Z_i, W_i; γ̂)

第三步:加入控制函数
Y_i = α·X_i + β·Z_i + λ·v̂_i + η_i

关键假设:
E[η_i | Z_i, W_i, v_i] = 0

理由:与线性情况相同

但注意:
如果第一阶段真的是非线性的,
而我们用线性来拟合,
那么v̂_i会有"规范误差"。

这可能导致λ̂有偏。

检验:
添加高阶项(如v̂²)看是否显著
如果显著,说明线性假设不对

7.2 实施问题

Q4: 为什么我的 v̂_i 与第二步方程中的 X_i 高度共线?这会导致什么?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
A: 这是常见的问题!让我解释。

定义:v̂_i = X_i - (γ̂₀ + γ̂_Z·Z_i + γ̂_W·W_i)

重新排列:
X_i = (γ̂₀ + γ̂_Z·Z_i + γ̂_W·W_i) + v̂_i
    = X̂_i + v̂_i

所以 Corr(X_i, v̂_i) 接近1

这是数学上的必然,不是什么问题。

为什么?

X_i被分解成两部分
1. 可预测部分 X̂_i(来自Z和W
2. 残差部分 v̂_i(不可预测部分)

它们是正交的(orthogonal):
Cov(X̂_i, v̂_i) = 0

所以虽然Corr(X_i, v̂_i)很高,
但这不会导致共线性问题!

原因:
虽然X_i和v̂_i相关
但它们的变差(variation)是独立的方向
(这是统计意义上的)

结果:
OLS估计仍然是有效的,标准误仍然可计算

检查方法:
计算方差膨胀因子 VIF(X_i)  VIF(v̂_i)
VIF通常不会很大(即使相关性看起来很大)

所以,不用担心!这是正常的。

Q5: 控制函数方法对样本量有什么要求?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
A: 关于样本量的要求:

最小样本量:
没有严格规定,但一般建议 n > 100

理由:
1. 第一阶段需要足够的变异性
   至少需要30-50个观测来稳定估计

2. 第二阶段需要更多
   因为有额外的变量v̂_i

3. 方差修正需要足够多的数据
   bootstrap方法需要n > 50效果最好

经验法则:
- n > 100: 可以使用
- n > 500: 可靠
- n > 1000: 非常好

当n很小时:
1. 使用bootstrap标准误而非渐近理论
2. 报告多个模型规范的稳健性
3. 考虑Bayesian方法(提供更好的小样本性质)

当n很大时:
1. 方差修正的重要性下降
   (渐近理论更准确)
2. 可以考虑更复杂的模型规范
3. 任何微小的规范错误都可能显著
   (需要特别小心)

Q6: 如何选择工具变量 W_i?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
A: 选择工具变量是最困难的部分。

要求(必须满足):
1. 排除约束:W_i不能直接进入结构方程
   (不影响Y_i,只通过X_i)

2. 相关性:W_i必须与X_i相关
   (相关性强弱由第一阶段R²衡量)

3. 外生性:W_i与ε_i无关
   (这通常假设,难以直接检验)

具体建议(按行业):

产业组织(定价问题):
✓ 投入价格(钢铁、电力、原油等)
✓ 竞争对手的特征
✓ 成本驱动因素
✗ 销售额的滞后值(可能与误差相关)

劳动经济学(工资问题):
✓ 教育改革(如加州的教育政策变化)
✓ 距离最近大学的距离(影响教育成本,不直接影响收入)
✓ 父母教育(影响自己教育,不直接影响收入)
✗ 个人能力(与工资直接相关)

环境经济学(污染问题):
✓ 上风向污染源
✓ 地理特征(海拔、纬度)
✓ 气候变量(风向、降水)
✗ 发展政策(与污染都可能内生)

一般原则:

最好的工具变量是:
"影响内生变量的决定,
但不影响结果变量"

这通常来自:
1. 政策变化(外生的!)
2. 地理变异(固定的)
3. 技术冲击(随机的)

7.3 诊断与检验

Q7: 如何检验控制函数假设是否成立?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
A: 这是一个困难的问题,因为有些假设原则上无法检验。

假设列表:

1. 排除约束:W_i不进入结构方程
   检验:✓ 可以直接检验
   方法:在结构方程中加入W_i,看系数是否显著
         H_0: W的系数 = 0

2. 工具相关性:W与X相关
   检验:✓ 可以检验
   方法:第一阶段F检验
         H_0: γ_W = 0
         建议:F > 10 (强工具)

3. 线性函数形式:ε_i = λ·v_i + η_i
   检验:✓ 可以部分检验
   方法:加入v_i的高阶项(v_i², v_i³等)
         如果显著,说明假设有问题

4. 条件外生性:E[η_i | Z_i, W_i, v_i] = 0
   检验:✗ 原则上无法直接检验
   方法:(间接的)进行Sargan/Hansen过度识别检验
         如果拒绝,说明可能有问题
         但不能确定是哪个假设违反

完整的诊断程序:

Step 1: 第一阶段诊断
  regress X Z W
  test W = 0          [弱工具变量?]

Step 2: 排除约束检验
  regress Y X Z W v_hat   [加入W]
  test W = 0          [W直接进入?]

Step 3: 函数形式检验
  gen v_hat_sq = v_hat^2
  regress Y X Z v_hat v_hat_sq
  test v_hat_sq = 0   [非线性?]

Step 4: 过度识别检验
  (如果有多于一个的W变量)
  reg Y X Z v_hat [得到残差e]
  correlate e W      [残差与工具相关?]

Step 5: 稳健性检查
  用不同的W组合
  改变函数形式
  检查结果是否一致

如果所有检验都通过:
  → 有信心使用这个估计

如果某些检验失败:
  → 需要重新考虑模型或工具变量

Q8: Sargan/Hansen 过度识别检验是什么意思?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
A: 当有多于一个的工具变量时,可以进行这个检验。

背景:
假设第一阶段有:
  X_i = γ₀ + γ_Z·Z_i + γ_{W1}·W_{1i} + γ_{W2}·W_{2i} + v_i

我们有两个工具变量W1和W2。
但我们只需要一个来识别参数α。

所以,W1和W2都应该满足排除约束(都不进入结构方程)。

Sargan检验的思想:
如果某个W变量实际上是内生的
(即与结构误差ε相关),
那么在第二步回归的残差中会有痕迹。

检验统计量:
1. 运行第二步,得到残差 ê_i
2. 用ê_i对Z_i和W_i回归
3. 计算J-statistic = n × R²

H_0:所有W都是外生的(排除约束成立)

在H_0下:
J ~ χ²_{#W - #X_endogenous}

在我们的例子中,自由度 = 2 - 1 = 1

如果J很大(p值小):
→ 拒绝H_0
→ 至少有一个W是内生的
→ 需要重新选择工具变量

Stata代码:

ivregress 2sls Y X Z (X = Z W1 W2), first
estat overid

第八部分:高级话题与展望

8.1 非线性模型中的控制函数

Logit/Probit 模型的控制函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
问题:
在二元选择模型中,结构方程是非线性的:

P(Y_i = 1) = Φ(α·X_i + β·Z_i + ε_i)

其中Φ是logit或probit累积分布函数。

X_i仍然可能是内生的,ε_i与X_i相关。

控制函数方法的扩展:

第一步:同之前
  X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i
  得到v̂_i

第二步:非线性结构方程
  Y_i = I[α·X_i + β·Z_i + λ·v̂_i + η_i > 0]

其中η_i是标准logit或标准正态

推导:
E[Y_i | X_i, Z_i, v̂_i] = Φ(α·X_i + β·Z_i + λ·v̂_i)

估计方法:
用最大似然估计(MLE),而非OLS

例子(Stata):
probit Y X Z v_hat, nolog

Poisson 模型的控制函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
结构方程:
E[Y_i | X_i, Z_i] = exp(α·X_i + β·Z_i + ε_i)

X_i内生,ε_i与X_i相关。

控制函数方法:

第一步:X_i = γ₀ + γ_Z·Z_i + γ_W·W_i + v_i

第二步:
  Y_i ~ Poisson(λ_i)
  λ_i = exp(α·X_i + β·Z_i + λ·v̂_i)

估计:
  poisson Y X Z v_hat

解释:
  λ̂表示内生性的强度

8.2 机器学习与控制函数的结合

高维数据中的第一阶段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
传统情况:
第一阶段使用线性模型,因为它:
1. 计算快
2. 理论清晰
3. 易于解释

但当特征很多时(p很大):
线性模型可能欠拟合
无法很好地预测X_i

解决方案:使用机器学习(ML)方法

例如:
使用Lasso、Random Forest或Neural Network
来估计第一阶段

关键原则:
1. 一定要用正则化
   (否则会过拟合)

2. 使用交叉验证选择超参数

3. 清楚理解:ML方法的偏差-方差权衡
   是否适合这个应用

最新进展(Chernozhukov et al.):
"Orthogonal/Partialing-Out"方法
允许使用高维模型(如Lasso)来做控制函数

8.3 动态模型与自适应成本

Collard-Wexler (2013)的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
在动态面板模型中运用控制函数:

需求方程:
  Q_{it} = α·P_{it} + β·X_{it} + ξ_{it} + ε_{it}

其中:
  ξ_{it}:持久性未观测质量
  ε_{it}:瞬间冲击

问题:
  P_{it}与ξ_{it}相关(定价考虑质量)

解决方案:

第一步:建立"政策函数"(Policy Function)
  P_{it} = f(ξ_{it}, 其他状态变量)

但ξ_{it}不可观测!

Collard-Wexler的技巧:
使用"初期条件"和"动态约束"
反演ξ_{it}的滞后值ξ_{it-1}

然后在需求方程中加入ξ̂_{it}(或其滞后)
作为控制变量

这比标准控制函数更复杂,
但允许处理动态中的内生性

第九部分:总结与最佳实践

9.1 何时使用控制函数法?

决策树

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
问题:我有内生变量,应该用什么方法?

    有好的工具变量吗?
      /         \
    是          否
    ↓           ↓
  能用IV?   能指定
  /  \      第一阶段模型?
 是   否      /      \
 ↓   ↓      是       否
 IV  ↓      ↓        ↓
     │   CF方法  需要其他
     │    推荐    方法*
  * 其他方法:
    - 匹配估计(Matching)
    - 合成控制(Synthetic Control)
    - 双重差分(DID)
    - 断点回归(RDD)
    等等(取决于具体情况)

快速对比:

                IV    CF    Matching
工具变量       必须   推荐   -
理论复杂度     中    高    低
计算难度       低    低    中
小样本表现     未知  未知  好
非线性模型     困难  容易  容易
反事实分析     困难  容易  困难
可重复性       高    中    低

9.2 实施检查清单

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
使用控制函数法前,检查:

□ 数据准备
  ☐ 变量明确定义
  ☐ 缺失值处理
  ☐ 异常值检查
  ☐ 样本量足够(n > 100)

□ 理论框架
  ☐ 内生变量明确
  ☐ 工具变量候选列表
  ☐ 经济学模型清晰
  ☐ 排除约束可信

□ 第一阶段估计
  ☐ 第一阶段R² > 0.3
  ☐ 工具变量相关性:F > 10
  ☐ 工具变量外生性可信
  ☐ 函数形式合理

□ 第二阶段估计
  ☐ 控制函数系数显著?
    (说明内生性确实存在)
  ☐ 参数符号合理?
  ☐ 大小在文献范围内?
  ☐ 标准误合理?

□ 诊断与检验
  ☐ 运行Sargan/Hansen检验
  ☐ 添加工具变量,看结果稳健性
  ☐ 改变函数形式,看结果稳健性
  ☐ 用不同样本(子样本分析)

□ 报告与展示
  ☐ 清楚解释第一阶段
  ☐ 展示与OLS的对比
  ☐ 报告修正的标准误
  ☐ 讨论经济学含义
  ☐ 承认局限

通过上述检查表 → 有信心发表
未通过某些项 → 需要进一步调查或改进

9.3 常见错误与更正

错误 症状 更正
弱工具变量 第一阶段 F < 5 找更好的工具或用其他方法
忘记修正方差 标准误看起来太小 使用 Newey 修正或 Bootstrap
规范误差 v_hat 的高阶项显著 考虑非线性第一阶段
多重共线性 VIF > 10 简化模型或增加样本
排除约束违反 W 在结构方程中显著 重新选择工具变量
过拟合 样本内拟合很好但预测差 增加正则化或简化
异质性忽视 参数在子样本中差异大 进行分组分析或允许异质性

最终建议

控制函数法是一个强大但复杂的工具。

它的优势:

  • ✓ 比 IV 更灵活
  • ✓ 在结构模型中自然融合
  • ✓ 可以处理多个内生变量
  • ✓ 计算相对简单

它的局限:

  • ✗ 对函数形式假设敏感
  • ✗ 需要手工计算标准误修正
  • ✗ 小样本性质不明确
  • ✗ 排除约束同样困难

什么时候用它?当你有好的理由相信第一阶段的函数形式,并且有好的工具变量时。

什么时候避免它?当你不确定函数形式,或者有其他更直接的因果识别策略时。

最后的建议:无论使用哪种方法, 诚实地报告假设进行充分的稳健性检查,这比选择"正确的"方法更重要。


希望这个完整的讲解对你有帮助!如果有具体问题,欢迎继续提问。

使用 Hugo 构建
主题 StackJimmy 设计