课程目录 · 已完成 0 / 7 个模块
实例:农机服务采纳模型
本模块用模拟数据完成一个完整的结构估计:生成数据、最大似然估计、检验拟合、计算补贴反事实,并说明模型的适用范围。页面中的实验用于演示,完整的计算由配套的 Stata 和 Python 程序完成。
问题与数据
问题:随机发放服务代金券使部分农户的净服务价格下降。据此估计价格敏感度与经营规模的收益,并预测普惠补贴下的采纳率和财政成本。
样本:700 个模拟农户。代金券随机分配;服务标价、经营规模、距离和质量均可观测。
选择:是否购买机械化服务。
估计:二元 logit 模型的最大似然估计。页面实验只改变价格与规模两个系数,截距、距离和质量系数固定;配套程序同时估计全部系数。
P(购买ᵢ=1) = Λ[β₀ + α·净价格ᵢ + β·log(1+规模ᵢ) + γ·距离ᵢ + δ·质量ᵢ]
说明:模型的推导、似然函数的数值算例、Newton 迭代、估计结果的解释、反事实的置信区间和蒙特卡洛检验,见 模块 6A。
数据说明:本例的参数真值和外生代金券由程序设定,只用于检验估计方法,不构成实证证据。实际的服务价格通常与未观测的质量、需求和供给能力相关,不能直接假定价格外生。
实验:似然函数与反事实
步骤 1 · 参数估计
最大化对数似然
调整两个参数,观察对数似然的变化;也可以用坐标搜索求最大值。在有限样本中,估计值接近但一般不等于程序设定的真值。
-0.45
0.15
步骤 2 · 政策反事实
改变补贴率,重新计算购买概率
补贴按实际购买支付,财政成本是每户预期成本。图中只改变农户净价格,服务供给和标价保持不变。
20%
可重复的计算步骤
| 阶段 | 要做什么 | 通过标准 |
|---|---|---|
| 1. 生成/读入数据 | 固定 seed;明确变量单位、选择时点与政策随机化 | 重新运行得到相同教学数据 |
| 2. 估计 | 最大化 logit 对数似然;报告估计值、标准误和收敛 | 模拟样本中能在抽样误差内回收真值 |
| 3. 拟合 | 比较观测和预测采纳率,并按净价格分组 | 不只报告总体平均 |
| 4. 反事实 | 改变净价格,计算采纳率与财政成本 | 使用同一估计参数,并传播不确定性 |
| 5. 边界 | 列明价格内生性、供给容量、进入与外推范围 | 结论不超过模型能回答的问题 |
Stata 程序
Stata 程序使用 logit 命令,该命令最大化二元选择模型的对数似然。程序的重点在于把估计系数解释为效用参数,并用估计参数进行政策模拟。
set seed 20260804
logit adopt net_price ln_land distance quality, vce(robust)
* 给定补贴率 s,重新计算净价格与预测概率
gen phat_cf = invlogit(_b[_cons] + _b[net_price] * listed_price * (1-s) ///
+ _b[ln_land] * ln_land + _b[distance] * distance ///
+ _b[quality] * quality)完整脚本还会输出按价格四分位的拟合表和 0–50% 补贴率的反事实 CSV/图形。
Python 程序
Python 程序只使用标准库,显式计算得分向量和信息矩阵,用 Newton–Raphson 法更新参数,无须安装其他软件包。对于更复杂的模型,可将同样的目标函数交给 SciPy 等优化库。
score, information = score_and_information(theta, farmers)
step = solve_linear_system(information, score)
theta = [value + change for value, change in zip(theta, step)]
if max(abs(change) for change in step) < tolerance:
breakPython 程序的输出及其解释
在 Python 3.13 中运行 structural-estimation-mechanization.py,输出如下:
constant: estimate= 0.100, SE=0.604, truth=-0.800
net_price: estimate=-1.795, SE=0.382, truth=-1.400
log_land: estimate= 0.822, SE=0.329, truth= 0.750
distance: estimate=-0.256, SE=0.062, truth=-0.180
quality: estimate= 0.393, SE=0.511, truth= 0.900
Converged in 7 iterations; log likelihood=-298.932
Q1: observed=0.274, predicted=0.272 Q4: observed=0.074, predicted=0.083
Subsidy=0%: adoption=0.128 Subsidy=20%: adoption=0.181, fiscal cost/farmer=0.043
Subsidy=50%: adoption=0.293, fiscal cost/farmer=0.182- 五个真值都在估计值 ±1.96 SE 内,但单个估计会偏离真值(价格系数 −1.795 vs −1.40),这就是抽样误差;模块 6A 的 300 次蒙特卡洛显示平均估计 −1.428、CI 覆盖率 0.963。
- Subsidy=0% 不是现状。反事实把净价格改为“标价 ×(1−s)”,s=0 相当于取消代金券,采纳率 0.128;现状(一半农户持 30% 券)的预测采纳率是 0.174。
- 反事实需要区间。原脚本只给点估计;模块 6A 的配套代码用 Krinsky–Robb 抽样给出 20% 补贴下的 95% 区间 [0.156, 0.212]。
- Stata 版在 Stata 中重新生成随机数,数据与 Python 版不同,系数会不同。若要三种软件逐位对照,请使用 6A 提供的共用数据文件
mechanization_sim.csv。
模型的局限
- 服务商进入:补贴提高需求后是否有新服务商进入?静态需求模型没有供给方。
- 容量与拥堵:旺季服务供给有限时,补贴可能抬价或延迟作业。
- 价格内生性:真实标价可能随未观测需求和质量变化,需要工具变量、实验价格或联合供需模型。
- 动态学习:农户可能先试用再更新质量认知,需要动态学习模型。
- 福利:采纳率不是福利。完整福利分析还需服务收益、成本、财政机会成本和供给者剩余。
扩展的顺序:应先完成并检验外生价格下的静态模型,再逐一加入价格内生性、未观测异质性、动态学习或服务商进入。同时加入多项扩展会使识别和计算问题难以诊断。相关模型见常见的扩展模型。