查看原文
其他

Stata:处理衡量偏误-变量误差模型的一些建议

连享会 连享会 2023-02-21

👇 连享会 · 推文导航 | www.lianxh.cn

连享会 · 2022 面板数据因果推断专题

作者:王舒瑶 (吉林大学)
邮箱:378807478@qq.com

[编者按]: 本文介绍的内容来自如下文献,特此致谢!
[Source]:Lockwood J. R., Daniel F. McCaffrey, 2020, Recommendations about estimating errors-in-variables regression in Stata, Stata Journal, 20(1): 116–130. -PDF-, -PDF2-, -Link-

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:


目录

  • 1. 引言

  • 2. 背景

  • 3. EIV 回归

    • 3.1 模型假设

    • 3.2 EIV 回归估计量

    • 3.3 标准误估计

    • 3.4 eivreg标准误的偏差

    • 3.5 Stata 命令用法

  • 4. 模拟研究

    • 4.1 模拟研究概述

    • 4.2  Stata 模拟程序和过程

  • 5. 结论

  • 参考资料



1. 引言

内生性有 3 个主要来源:「遗漏变量」、「互为因果」和「衡量偏误」。其中第三种「衡量偏误」受到的关注相对较少,但若存在这一问题,会导致研究者无法一致地估计解释变量的系数。

在以往的推文 第三种内生性:衡量偏误(测量误差)如何检验-dgmtest?中,我们介绍了如何判断是否存在「衡量偏误」。而在推文 xtewreg:面板数据存在衡量偏误-测量偏误时如何估计?中,我们进一步对「衡量偏误」的应对办法 xtewreg 进行探讨。

在本文中,我们对 eivregsem 这两种常见的变量误差 (errors-in-variables, EIV) 回归方法进行比较,并给出建议。

 

2. 背景

举个例子来导入:在可以用来估计教育政策对学生成就的影响的传统教育生产函数模型中,当前的研究成果是兴趣的投入和先前的成就之间的函数。 但是,先前的成就是不能被观测到的。 相反,它是通过测试分数来衡量的,该分数通常是从美国各州或学区进行的标准化评估中获得的。 使用易于出错的度量代替相应的潜在变量来拟合模型通常会导致所有模型参数的估计值不一致,而不仅仅是与误差测量的变量相对应的回归系数。

在已知有关衡量误差文献中,我们通常使用两种主要方法来获得一致的估计量:eivregsemeivreg 使用矩量法调整来解决测量中的误差。 sem 是为回归模型中的因变量、自变量和测量误差指定联合高斯分布,然后使用最大似然估计回归系数。

 

3. EIV 回归

3.1 模型假设

i = 1 到 N,让 ( , , , , ) 与具有有限第四矩的分布是独立且均匀分布的 (IID) 。

, 是长度均为p的向量。

随机变量 是标量。

, 是可以观测到的数据,而 , , 是不可以观测到的数据。

我们的目标是估计出 ,但问题是“真实”的 是错误地由 估计的。

 

3.2 EIV 回归估计量

如果测量误差 的方差-协方差矩阵是已知的或可以估计的,则 EIV 回归估计使用矩量法来估计 。在 3.1 的模型假设下,假设其他标准正则条件成立,则 的 EIV 回归估计量是一致的。

我们将注意力集中在 是具有元素的对角矩阵的情况下,因此 的不同分量中的测量误差是相互不相关的。 我们专注于这种情况,因为此假设通常在应用程序中进行,并且 eivreg 要求此限制。 在 不是对角矩阵的情况下,仍然可以很好地定义 EIV 回归估计量,在这种情况下,Stata 用户可以使用 sem 而不是 eivreg ,因为 sem 的语法足够通用,可以允许 是非对角矩阵。

 

3.3 标准误估计

如上所述,在假设成立的情况下, eivreg 使用的矩方法算法和 sem 使用的最大似然算法在理论上得出相同的 值。原因是,两种算法都产生了一组相同的估计方程组,其解为

在实践中,只要存在给定的观测数据和假定的可靠性,并且只要 sem 使用的迭代算法收敛,那么这两个命令将报告相同的 值,直到数值上的差异很小。

但是,这些命令没有使用相同的方法来估计 的方差-协方差矩阵,而 eivreg 所使用的方法将倾向于低估在潜在变量建模中通常做出的假设下估算器的实际抽样方差。原因在于,对于下述公式 (3) :

的替代表达式 (4):

eivreg 估计出来的 , 是上述表达式 (4) 右侧的第二项,第一项被忽略了。

仅在所有协变量及其对应的测量误差均已固定的前提下, eivreg 报告的 才是适当的。 该假设通常与从总体中随机抽取单位不一致,并且在具有测量误差的应用中特别受限制,因为它也以未观察到的测量误差的固定值为条件。

此外,即使在需要保证这些假设的应用中,eivreg 使用的方差估计量也将适合于表征估计回归系数的抽样变异性,但不适用于表征这些估计量的均方误差。因为 通常不等于

另外,由 sem 报告的 估计值会产生标准误差估计值,该估计值与协变量的随机抽样、测量误差以及总体分布的结果一致,隐含地解释了上述 的替代表达式 (4) 右侧的两个项。

 

3.4 eivreg标准误的偏差

通常很难评估表达式 (4) 中两个项的相对大小,但是一些基本结果是显而易见的。 对于固定的 N 和固定的 , 收敛到零且 收敛到 ,即在所有变量的随机抽样下, 的 OLS 估计量的方差。

还要注意, 不依赖于 。因此,对于固定的 N 和 小于 1 的固定可靠性, 由于 趋近 0, 占主导地位。因为 eivreg 忽略了这一项,eivreg 报告的标准误差将趋向于负偏,并且相关的置信区间的覆盖率将小于名义水平,无论样本量大小。

 

3.5 Stata 命令用法

eivreg 在实际操作时与 reg 类似,如:

. eivreg y x c

sem ( structural equation modeling ) 是一种结构方程模型,它可以同时处理潜变量 ( 难以直接准确测量 ) 和显变量 ( 利用显变量去间接测量显变量 ) 。以单因素测量模型为例:

. sem ( x1 x2 x3 x4 <- X )

其中,x1 x2 x3 x4 为显变量,X 为潜变量。

 

4. 模拟研究

4.1 模拟研究概述

我们进行了简单的模拟研究,以证明 eivreg 报告的标准误差与 sem 报告的标准误差之间的实际差异。

我们考虑 (即截距和标量预测变量)的情况,并且仅关注预测变量的估计系数。 我们的模拟改变了三个因素:样本量 N ,真实回归的 和可靠性 r。

对于每个模拟条件和蒙特卡洛复制,我们使用模拟数据, 分别基于eivregsem 来计算 的 EIV 回归估计 b 及其相关的标准误差估计。 对于 eivreg ,我们既跟踪了 b 的报告标准差,又跟踪了使用 250 个自抽样估计的标准误。 我们使用250个自抽样的样本,因为根据 Efron 和 Tibshirani (1993, 52) 的大多数情况,这个数量应该足够了,而且计算时间并不是很长。

在对模拟研究的初步探索中,我们发现了具有 EIV 回归估计量并已通过 eivreg 成功计算但其 sem 并未从其默认起始值收敛到该解的模拟数据集。因此,我们修改了对 sem 的调用,以使用模型参数的 MLE 作为起始值。 以这种方式初始化参数可导致 sem 迅速收敛,并在 semeivreg 之间估计出回归系数,这表明所有模拟数据集的数值差异都可以忽略不计。

模拟结果与 eivreg 的负偏差分析结果一致。 使用 eivreg 报告的标准误, 的 95% 置信区间的覆盖率不到 95% 。 在 100 个模拟条件下,使用 eivreg 报告的标准误的覆盖概率范围为 0.58 至 0.95 ,平均值为 0.87 。 当 大且 r 小时,无论样本大小 N 如何,覆盖率都更差。当 小而 r 大时,无论 N 大小,覆盖率都接近名义水平。 eivreg 报告的平均标准误差与 b 的估计抽样标准误之比在 0.42 至 1.02 之间,平均值为 0.82 ,这与置信区间的掩盖度一致。

使用 sem 报告的标准误或自举标准误计算的置信区间更接近名义覆盖率。 对于 sem ,覆盖范围从 0.94 到大于 0.99 ,平均值为 0.97。 由 sem 报告的平均标准误差与 b 的估计抽样标准误之比在 0.95 至 1.74 之间,平均值为 1.14 ,与置信区间覆盖范围略有超出名义水平一致。 对于自举标准误,覆盖范围在 0.92 至 0.96 之间,平均值为 0.95 ,平均标准误差与 b 的估计采样标准误之比在 0.95 至 1.05 之间,平均值为 0.99。

 

4.2  Stata 模拟程序和过程

4.2.1 运行一次的模拟迭代程序

先使用 program drop 将原有程序从内存中删除。如果内存中原本不存在这个程序,那么 program drop 将返回一个错误。在 program drop 之前输入 capture 将捕获此错误并允许代码块继续运行。

然后定义我们此次的程序 simit ,定义程序后,输入 simit ,Stata 将在 programend 之间运行所有命令。选项 rclass 告诉 Stata 我们想要使用 return 返回程序中的值。

接着用 syntax 定义程序的语法,nobs ( ) 表示观察值的计数,integer 表示需要输入整数;rsq ( ) 和 lambda ( ) 是参数,real 表示需要输入实数。

随后就都是对运行一次的模拟迭代程序的语句进行设计。

最后一行是 end ,它告诉 Stata 你已经完成了对程序 simit 的定义。

capture program drop simit
/* *********************************************** */
/* program for running one iteration of simulation */
/* *********************************************** */
program simit, rclass
syntax, nobs(integer) rsq(real) lambda(real)
preserve
set obs `nobs'
/* generate data */
generate double xstar = rnormal(0.0, 1.0)
generate double err = rnormal(0.0, sqrt( (1.0 - `rsq') / `rsq' ))
generate double u = rnormal(0.0, sqrt( (1.0 - `lambda') / `lambda'))
generate double xobs = xstar + u
generate y = 0.0 + 1.0*xstar + err
/* proceed if EIV is possible given observed data and reliability */
quietly correlate y xobs
if (`lambda' > r(rho)^2) {
return scalar eiv_ok = 1
/* run -eivreg- with reported standard errors ("eiv") */
eivreg y xobs, reliab(xobs `lambda')
local b_init = _b[xobs]
scalar cieiv_l = _b[xobs]-1.96*_se[xobs]
scalar cieiv_u = _b[xobs]+1.96*_se[xobs]
return scalar b_eiv = _b[xobs]
return scalar se_eiv = _se[xobs]
return scalar cover_eiv = cond(cieiv_l<1 & cieiv_u>1,1,0)
/* run -eivreg- with bootstrapped standard errors ("beiv") */
bootstrap, reps(250): eivreg y xobs, reliab(xobs `lambda')
scalar cibeiv_l = _b[xobs]-1.96*_se[xobs]
scalar cibeiv_u = _b[xobs]+1.96*_se[xobs]
return scalar b_beiv = _b[xobs]
return scalar se_beiv = _se[xobs]
return scalar cover_beiv = cond(cibeiv_l<1 & cibeiv_u>1,1,0)
/* run -sem-, initializing regression coefficient at -eivreg- solution, */
/* and initializing var(X) and var(Y|X) to their MLEs */
quietly summarize xobs
local vX_init = r(Var) * ((`nobs' - 1)/`nobs') * `lambda'
quietly summarize y
local veY_init = (r(Var) * ((`nobs' - 1)/`nobs')) - ///
(`b_init'*`b_init'*`vX_init')
capture sem (xobs <- X) (y <- (X, init(`b_init'))), ///
var((X, init(`vX_init'))) var((e.y, init(`veY_init'))) ///
reliab(xobs `lambda')
matrix B = e(b)
matrix vB = e(V)
scalar b_sem = B[1,3]
scalar se_sem = sqrt(vB[3,3])
scalar cisem_l = b_sem -1.96*se_sem
scalar cisem_u = b_sem +1.96*se_sem
return scalar b_sem = b_sem
return scalar se_sem = se_sem
return scalar cover_sem = cond(cisem_l<1 & cisem_u>1,1,0)
return scalar sem_status = _rc
}
else {
return scalar eiv_ok = 0
}
restore
end

 

4.2.2 条件和蒙特卡罗复制的循环模拟

蒙特卡罗模拟是指通过大量随机抽样进行模拟,最终得出变量的累计概率分布。设置 seed 是为了让实验可以重复。主体循环是先取 obs_seq ,再取 rsq_seq ,最后取 lambda_seq ,例如: 第一次取 100 0.10 0.50 ,第二次取 100 0.10 0.60 ,…… ,第六次取 100 0.30 0.50 ,以此类推。 nsim 表示循环重复 1800 遍。

关于蒙特卡罗模拟的一些基本介绍,可以参看以往推文 stata中计算公式命令_Stata:学点蒙特卡洛模拟分析

/* ************************************************************ */
/* loop simulation over conditions and Monte Carlo replications */
/* ************************************************************ */
set more off
set seed 1417
set linesize 140

local nobs_seq 100 500 1000 5000
local rsq_seq 0.10 0.30 0.50 0.70 0.90
local lambda_seq 0.50 0.60 0.70 0.80 0.90
local nsim 1800
local filename results_all
tempname simulation

postfile `simulation' numok numsemconv nobs rsq lambda ///
b_eiv_mean b_eiv_sd se_eiv_mean cover_eiv ///
b_beiv_mean b_beiv_sd se_beiv_mean cover_beiv ///
b_sem_mean b_sem_sd se_sem_mean cover_sem ///
using `filename', replace

display "$S_TIME $S_DATE"

foreach nobs of local nobs_seq {
foreach rsq of local rsq_seq {
foreach lambda of local lambda_seq {
simulate eiv_ok=r(eiv_ok) sem_status=r(sem_status) ///
b_eiv=r(b_eiv) se_eiv=r(se_eiv) cover_eiv=r(cover_eiv) ///
b_beiv=r(b_beiv) se_beiv=r(se_beiv) cover_beiv=r(cover_beiv) ///
b_sem=r(b_sem) se_sem=r(se_sem) cover_sem=r(cover_sem), ///
reps(`nsim'): simit, nobs(`nobs') rsq(`rsq') lambda(`lambda')
quietly summarize eiv_ok
scalar numok = r(sum)
generate tmp = (sem_status==0)
quietly summarize tmp
scalar numsemconv = r(sum)
drop tmp

/* compute summary statistics to save, */
/* keeping cases where EIV possible and -sem- converged. */
/* also check that estimated coefficients are the same */
keep if ((sem_status==0) & (eiv_ok==1))
generate d = b_sem - b_eiv
summarize d
drop d
foreach var of varlist ///
b_eiv se_eiv cover_eiv ///
b_beiv se_beiv cover_beiv ///
b_sem se_sem cover_sem {
quietly summarize `var'
scalar `var'_mean=r(mean)
}
foreach var of varlist b_eiv b_beiv b_sem {
quietly summarize `var'
scalar `var'_sd=r(sd)
}
post `simulation' ///
(numok) (numsemconv) (`nobs') (`rsq') (`lambda') ///
(b_eiv_mean) (b_eiv_sd) (se_eiv_mean) (cover_eiv_mean) ///
(b_beiv_mean) (b_beiv_sd) (se_beiv_mean) (cover_beiv_mean) ///
(b_sem_mean) (b_sem_sd) (se_sem_mean) (cover_sem_mean)
clear
}
}
}

postclose `simulation'

display "$S_TIME $S_DATE"

use "`results_all'", clear
sort nobs rsq lambda
list
outsheet using "results_all.csv", comma nolabel replace

需要注意的是,4.2.1 和 4.2.2 是一个整体,如果想要跑出最终的模拟结果,两部分命令缺一不可。其中前面部分的目的在于设计 simit 的 program ,后面部分的目的在于运用这个 program 来完成蒙特卡洛模拟。按照目前的参数设置 (4 个 nobs_seq,5 个 rsq_seq,5 个 lambda_seq) ,该程序一共跑 100 组 (4 * 5 * 5) ,每组模拟 1800 次,最后生成 100 条数据,所以 Stata 跑起来还是很耗费时间的。由于 100 个结果展示出来篇幅过于大,笔者在这里只展示 10 个模拟结果 (nobs_seq 取值 100 ,rsq_seq 取值 0.10、0.30, lambda_seq 取值 0.50、0.60、0.70、0.80、0.90) ,结果如下表所示:

nobsrsqlambdab_eiv_meanb_eiv_sdse_eiv_meancover_eivb_beiv_meanb_beiv_sdse_beiv_meancover_beivb_sem_meanb_sem_sdse_sem_meancover_sem
1000.10.50.96881790.5065480.44730570.88888890.96881790.5065480.47178290.88888890.96881790.50654810.48217620.9444444
1000.10.60.94259980.46509040.39352030.88888890.94259980.46509040.39958310.94444440.94259980.46509040.41092560.9444444
1000.10.71.0899050.35892290.34253170.88888891.0899050.35892290.34975990.88888891.0899050.35892290.35435880.9444444
1000.10.80.9762970.30394940.34713710.9762970.30394940.34985290.94444440.9762970.30394940.34935641
1000.10.90.98236720.25143690.313820310.98236720.25143690.313961410.98236710.25143690.31291751
1000.30.51.0568970.20124560.210889411.0568970.20124560.21909440.94444441.0568960.20124560.28006361
1000.30.60.95677880.16218720.19538150.94444440.95677880.16218720.20732080.94444440.95677880.16218720.2287461
1000.30.70.97480290.17273750.181766510.97480290.17273750.189254610.97480290.17273750.20067581
1000.30.80.94404360.19347160.17774680.88888890.94404360.19347160.18868450.94444440.94404360.19347160.18565880.8888889
1000.30.91.051790.15809330.16710660.88888891.051790.15809330.16404820.88888891.051790.15809330.17003320.8888889

表格的前三列显示的是 nobs_seqrsq_seqlambda_seq 的取值情况,随后依次展示 eivreg,自抽样标准误增强的 eivregsem 的系数估计结果,模拟结果显示这三者对系数大小的估计情况差不多,但是 eivreg 的标准误会偏低,置信区间的覆盖率更小。自抽样标准误增强的 eivreg 可以在一定程度上纠正 eivreg 的偏差,但是效果依旧不如 sem

 

5. 结论

变量误差( EIV )回归是在具有易错协变量的线性模型中进行一致估计的标准方法, Stata 命令 eivregsem 均可实现这一目的。 但是,在通常做出的假设下, eivreg 报告的标准误会负偏,从而导致置信区间覆盖率低于名义水平。 因此,在 EIV 回归的大多数实际应用中,单独使用 sem 或使用自抽样标准误增强的 eivreg 比单独使用 eivreg 更好。

 

参考资料

  • Lockwood J. R., Daniel F. McCaffrey, 2020, Recommendations about estimating errors-in-variables regression in Stata, Stata Journal, 20(1): 116–130. -PDF-, -PDF2-, -Link-
  • Meijer, E., E. Oczkowski, T. Wansbeek, 2021, How measurement error affects inference in linear regression, Empirical Economics, 60 (1): 1-25. -PDF-
  • 第三种内生性:衡量偏误(测量误差)如何检验-dgmtest?
  • xtewreg:面板数据存在衡量偏误-测量偏误时如何估计?

课程推荐:因果推断实用计量方法
主讲老师:邱嘉平教授
🍓 课程主页https://gitee.com/lianxh/YGqjp

New! Stata 搜索神器:lianxhsongbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉  使用:
. lianxh DID 倍分法
. songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存