Skip to content

[ols] Translation Updates #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 2, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 72 additions & 76 deletions lectures/ols.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,26 @@ tags: [hide-output]

## 概述

线性回归是分析两个或多个变量之间关系的标准工具
线性回归是分析两个或多个变量之间关系的基础工具

在本讲中,我们将使用Python包`statsmodels`来估计、解释和可视化线性回归模型。
在本讲中,我们将使用Python的`statsmodels`包来探索线性回归分析。我们将学习如何:

在此过程中,我们将讨论多个主题,包括
- 建立和估计简单及多元线性回归模型
- 通过图表直观展示分析结果
- 理解内生性问题和遗漏变量偏差
- 使用两阶段最小二乘法处理内生性

- 简单和多元线性回归
- 可视化
- 内生性和遗漏变量偏差
- 两阶段最小二乘法
通过这些内容,你将掌握使用Python进行线性回归分析的基本技能。

作为示例,我们将复现Acemoglu、Johnson和Robinson具有开创性意义的论文{cite}`Acemoglu2001`中的结果。

* 您可以在[这里](https://economics.mit.edu/research/publications/colonial-origins-comparative-development-empirical-investigation)下载论文。

在这篇论文中,作者强调了制度在经济发展中的重要性。

该论文的主要贡献是使用殖民者死亡率作为制度差异的*外生*变异来源
该论文的一个重要创新是利用了早期殖民者的死亡率数据,作为各地区制度差异的*外生*来源

这种变化对于确定是制度导致更大的经济增长,而不是反过来,是必要的
这种方法对于确定因果关系至关重要 - 即制度质量的提高会带来经济增长,而不是经济发展反过来改善了制度

让我们从一些导入开始:

Expand All @@ -76,24 +76,23 @@ sns.set_theme()

### 预备知识

本讲座假定您熟悉基础计量经济学
本讲座需要基础计量经济学知识

关于这些主题的入门教材,请参见例如{cite}`Wooldridge2015`。
如果你需要复习相关概念,可以参考{cite}`Wooldridge2015`等教材

## 简单线性回归

{cite}`Acemoglu2001`希望确定制度差异是否可以帮助解释观察到的经济结果
让我们从一个有趣的经济学问题开始 - 制度差异是否会影响一个国家的经济发展水平?这正是{cite}`Acemoglu2001`试图回答的问题

我们如何衡量*制度差异*和*经济结果*?

在这篇论文中,

- 经济结果用1995年经汇率调整的人均GDP对数表示。
- 制度差异用[政治风险服务集团](https://www.prsgroup.com/)构建的1985-95年间平均防止征用指数表示
- 制度差异用[政治风险研究组织](https://www.prsgroup.com/)构建的1985-95年间平均防止征用风险指数表示

这些变量和论文中使用的其他数据可以在Daron Acemoglu的[网页](https://economics.mit.edu/people/faculty/daron-acemoglu/data-archive)上下载。

我们将使用pandas的`.read_stata()`函数将`.dta`文件中的数据读入数据框
这些数据以及论文中使用的其他变量都可以从Daron Acemoglu的[个人主页](https://economics.mit.edu/people/faculty/daron-acemoglu/data-archive)下载。
接下来,我们用pandas的`.read_stata()`函数来读取这些存储在`.dta`格式文件中的数据

```{code-cell} ipython3
df1 = pd.read_stata('https://github.com/QuantEcon/lecture-python/blob/master/source/_static/lecture_specific/ols/maketable1.dta?raw=true')
Expand All @@ -107,13 +106,13 @@ df1.plot(x='avexpr', y='logpgp95', kind='scatter')
plt.show()
```

该图显示了防止征用保护与人均GDP对数之间存在相当强的正相关关系
从散点图中可以清楚地看到,一个国家的防止征用保护水平与其人均GDP之间存在明显的正相关关系

具体来说,如果更高的防止征用保护是衡量制度质量的指标,那么更好的制度似乎与更好的经济成果(更高的人均GDP)呈正相关
换句话说,如果我们把防止征用保护视为衡量制度质量的指标,那么数据表明制度质量越好的国家,经济表现(以人均GDP衡量)也往往越好

根据图表,选择线性模型来描述这种关系似乎是一个合理的假设
从散点图的形状来看,用一条直线来拟合这种关系是比较合适的。因此我们可以用一个简单的线性模型来描述它们之间的关系

我们可以将模型写作
我们可以将这个模型写作

$$
{logpgp95}_i = \beta_0 + \beta_1 {avexpr}_i + u_i
Expand All @@ -125,15 +124,13 @@ $$
- $\beta_1$ 是线性趋势线的斜率,表示防止风险保护对人均GDP对数的*边际效应*
- $u_i$ 是随机误差项(由于模型未包含的因素导致观测值偏离线性趋势)

从视觉上看,这个线性模型涉及选择一条最佳的直线

拟合数据,如下图所示(图2,引用自{cite}`Acemoglu2001`)
直观来看,这个线性模型涉及选择一条最佳的直线来拟合数据,如下图所示(图2,引用自{cite}`Acemoglu2001`)

```{code-cell} ipython3
# 删除NA值是使用numpy的polyfit所必需的
# 使用numpy的polyfit需要我们删除缺失值
df1_subset = df1.dropna(subset=['logpgp95', 'avexpr'])

# 仅使用"基础样本"用于绘图目的
# 仅使用'baseco'为1的样本用于绘图目的
df1_subset = df1_subset[df1_subset['baseco'] == 1]

X = df1_subset['avexpr']
Expand Down Expand Up @@ -170,15 +167,17 @@ $$

其中$\hat{u}_i$是观测值与因变量预测值之间的差异。

为了估计常数项$\beta_0$,我们需要在数据集中添加一列1(考虑如果将$\beta_0$替换为$\beta_0 x_i$且$x_i = 1$时的方程)
为了估计截距项$\beta_0$,我们需要在数据集中添加一列值为1的常数列。

这样做的原因是,如果我们将$\beta_0$写成$\beta_0 x_i$的形式,其中$x_i = 1$,那么这一项就代表了回归线在y轴上的截距。

```{code-cell} ipython3
df1['const'] = 1
```

现在我们可以使用OLS函数在`statsmodels`中构建我们的模型。

我们将在`statsmodels`中使用`pandas`数据框,不过标准数组也可以作为参数使用
我们将在`statsmodels`中使用`pandas`数据类型,不过标准数组也可以作为参数使用

```{code-cell} ipython3
reg1 = sm.OLS(endog=df1['logpgp95'], exog=df1[['const', 'avexpr']], \
Expand Down Expand Up @@ -210,29 +209,21 @@ print(results.summary())

- 截距 $\hat{\beta}_0 = 4.63$。
- 斜率 $\hat{\beta}_1 = 0.53$。
- 正的 $\hat{\beta}_1$ 参数估计值表明,
制度质量对经济结果有正面影响,正如
我们在图中所看到的。
- $\hat{\beta}_1$ 的p值为0.000,表明
制度对GDP的影响在统计上显著(使用p <
0.05作为拒绝规则)。
- R方值为0.611表明约61%的人均GDP对数
变异可由防止征收保护来解释。
- 正的 $\hat{\beta}_1$ 参数估计值表明,制度质量对经济结果有正面影响,正如我们在图中所看到的。
- $\hat{\beta}_1$ 的p值为0.000,表明制度对GDP的影响在统计上显著(使用p < 0.05作为判断是否显著的标准)。
- R方值为0.611,这意味着防止征收保护这一变量可以解释约61%的人均GDP对数的变化。

使用我们的参数估计,我们现在可以将估计关系写为

$$
\widehat{logpgp95}_i = 4.63 + 0.53 \ {avexpr}_i
$$

这个方程描述了最适合我们数据的直线,如图2所示。

我们可以使用这个方程来预测特定征收保护指数值
对应的人均GDP对数水平。
这个方程描述了最符合我们数据的直线,如图2所示。

例如,对于一个指数值为7.07的国家(这是
我们可以使用这个方程来预测特定征收保护指数值对应的人均GDP对数水平。

在数据集中),我们发现他们预测的1995年人均GDP对数值为8.38。
例如,对于一个指数值为7.07的国家(这是数据集中最高的指数值),我们发现他们预测的1995年人均GDP对数值为8.38。

```{code-cell} ipython3
mean_expr = np.mean(df1_subset['avexpr'])
Expand All @@ -244,9 +235,7 @@ predicted_logpdp95 = 4.63 + 0.53 * 7.07
predicted_logpdp95
```

获得这个结果有一个更简单(也更准确)的方法,就是使用
`.predict()` 并设置 $constant = 1$ 和
${avexpr}_i = mean\_expr$
获得这个结果有一个更简单(也更准确)的方法,就是使用`.predict()` 并设置 $constant = 1$ 和 ${avexpr}_i = mean\_expr$

```{code-cell} ipython3
results.predict(exog=[1, mean_expr])
Expand All @@ -260,17 +249,14 @@ results.predict(exog=[1, mean_expr])

```{code-cell} ipython3
# 从整个样本中删除缺失观测值

df1_plot = df1.dropna(subset=['logpgp95', 'avexpr'])

# 绘制预测值

fix, ax = plt.subplots()
ax.scatter(df1_plot['avexpr'], results.predict(), alpha=0.5,
label='predicted')

# 绘制观测值

ax.scatter(df1_plot['avexpr'], df1_plot['logpgp95'], alpha=0.5,
label='observed')

Expand All @@ -283,18 +269,20 @@ plt.show()

## 扩展线性回归模型

到目前为止,我们只考虑了制度对经济表现的影响 - 几乎可以肯定还有许多其他因素影响着GDP,但这些因素尚未包含在我们的模型中
到目前为止,我们只关注了制度对经济表现的影响。但显然,一个国家的GDP还受到许多其他因素的影响。我们的模型目前还没有考虑这些因素

忽略影响$logpgp95_i$的变量将导致**遗漏变量偏差**,从而产生有偏和不一致的参数估计
如果我们忽略了这些影响$logpgp95_i$的重要变量,就会产生所谓的**遗漏变量偏差**。这种偏差会导致我们的参数估计既有偏又不一致

我们可以通过添加其他可能影响$logpgp95_i$的因素,将双变量回归模型扩展为**多变量回归模型**。
为了解决这个问题,我们可以将原来的双变量回归扩展为**多变量回归模型**,把其他可能影响$logpgp95_i$的因素也纳入考虑

{cite}`Acemoglu2001`考虑了其他因素,如
{cite}`Acemoglu2001`中,作者考虑了多个可能影响经济发展的因素

- 气候对经济结果的影响;使用纬度作为代理变量
- 影响经济表现和制度的其他差异,如文化、历史等;通过使用大陆虚拟变量来控制
- 气候条件:他们使用纬度作为衡量气候的代理变量,因为纬度与温度、降水等气候特征密切相关
- 地区特征:通过引入大陆虚拟变量(如亚洲、非洲等),来控制不同地区在文化、历史等方面的差异

让我们使用`maketable2.dta`中的数据来估计论文中考虑的一些扩展模型(表2)
让我们来看看这些扩展模型的估计结果。

我们将使用`maketable2.dta`中的数据,复现论文表2中的分析

```{code-cell} ipython3
df2 = pd.read_stata('https://github.com/QuantEcon/lecture-python/blob/master/source/_static/lecture_specific/ols/maketable2.dta?raw=true')
Expand Down Expand Up @@ -339,28 +327,36 @@ print(results_table)

## 内生性

正如 {cite}`Acemoglu2001` 所讨论的,OLS模型可能存在**内生性**问题,导致模型估计有偏差且不一致
{cite}`Acemoglu2001` 指出,使用OLS模型估计制度对经济发展的影响时,我们面临一个重要的挑战 - **内生性**问题。这个问题会导致我们的估计结果产生偏差

具体来说,制度和经济结果之间可能存在双向关系
为什么会存在内生性呢?主要是因为制度质量和经济发展水平之间可能相互影响

- 较富裕的国家可能有能力负担或倾向于选择更好的制度
- 影响收入的变量可能也与制度差异相关
- 指数的构建可能存在偏差;分析师可能倾向于认为收入较高的国家拥有更好的制度

为了解决内生性问题,我们可以使用**两阶段最小二乘法(2SLS回归)**,这是OLS回归的扩展
要解决这个问题,我们可以采用一种叫做**两阶段最小二乘法(2SLS)**的方法

这种方法需要用一个变量来替代内生变量${avexpr}_i$,该变量必须:

1. 与${avexpr}_i$相关
1. 与误差项不相关(即不应直接影响因变量,否则由于遗漏变量偏差会与$u_i$相关)
2. 与误差项不相关(即不应直接影响因变量,否则由于遗漏变量偏差会与$u_i$相关)

这组新的回归变量被称为**工具变量**,其目的是消除我们在衡量制度差异时的内生性问题。

{cite}`Acemoglu2001`的主要贡献在于使用殖民者死亡率作为制度差异的工具变量。

他们假设殖民者较高的死亡率导致了更具掠夺性质的制度建立(对征收的保护较少),而这些制度一直延续至今。
他们的论证是这样的:在死亡率高的地区,殖民者倾向于建立掠夺性的制度,主要目的是快速榨取资源而不是长期发展。

这些制度往往对私有财产保护不足,容易被征收。

而且由于制度具有持续性,这种制度特征一直延续到了今天。

通过散点图({cite}`Acemoglu2001`中的图3),我们可以看到防止征收风险与殖民者死亡率呈负相关,这与作者的假设相符,满足了有效工具变量的第一个条件。
我们可以通过散点图(见{cite}`Acemoglu2001`的图3)验证这一假设。

图中显示,殖民者死亡率越高的地区,其防止征收风险指数越低(即财产保护程度越差)。

这种负相关关系支持了作者的假设,也满足了工具变量的第一个条件

```{code-cell} ipython3
# Dropping NA's is required to use numpy's polyfit
Expand Down Expand Up @@ -396,8 +392,7 @@ plt.show()

{cite}`Acemoglu2001`认为这种情况不太可能,因为:

- 大多数殖民者死亡是由疟疾和黄热病引起的,
对当地人的影响有限。
- 大多数殖民者死亡是由疟疾和黄热病引起的,对当地人的影响有限。
- 非洲或印度等地区的当地人的疾病负担似乎并不高于平均水平,
这一点从殖民前这些地区相对较高的人口密度可以得到证实。

Expand All @@ -417,7 +412,7 @@ $$
{avexpr}_i = \delta_0 + \delta_1 {logem4}_i + v_i
$$

估计这个方程所需的数据位于`maketable4.dta`文件中(仅使用完整数据进行估计,由`baseco = 1`标识)
让我们使用`maketable4.dta`文件中的数据来估计这个方程。我们只使用完整的观测值样本(用`baseco = 1`标识的数据)。

```{code-cell} ipython3
# 导入并选择数据
Expand Down Expand Up @@ -453,16 +448,19 @@ results_ss = sm.OLS(df4['logpgp95'],
df4[['const', 'predicted_avexpr']]).fit()
print(results_ss.summary())
```
通过第二阶段回归,我们得到了制度对经济发展影响的无偏且一致的估计结果。

第二阶段回归结果为我们提供了制度对经济结果影响的无偏且一致的估计
结果表明,制度质量与经济发展之间存在比OLS估计更强的正相关关系。这说明在控制内生性问题后,制度的影响实际上比简单回归显示的更大

结果显示出比OLS结果更强的正相关关系
不过需要注意的是,虽然这种分步骤进行OLS回归的方法可以得到正确的参数估计,但由于没有考虑到第一阶段估计的不确定性,标准误差的计算并不准确

请注意,虽然我们的参数估计是正确的,但我们的标准误差并不准确,因此不建议"手动"(通过分阶段OLS)计算2SLS
因此在实践中,我们不建议用这种"手动"方式来进行2SLS估计

我们可以使用[linearmodels](https://github.com/bashtage/linearmodels)包(statsmodels的扩展)在一步中正确估计2SLS回归。

注意,在使用`IV2SLS`时,外生变量和工具变量在函数参数中是分开的(而之前工具变量包含了外生变量)
注意,在使用`IV2SLS`时,外生变量和工具变量在函数参数中是分开的(而之前工具变量包含了外生变量)。

在`statsmodels`中,我们使用`exog`参数来指定外生变量,使用`instruments`参数来指定工具变量。

```{code-cell} ipython3
iv = IV2SLS(dependent=df4['logpgp95'],
Expand All @@ -481,20 +479,20 @@ print(iv.summary)

我们已经演示了在`statsmodels`和`linearmodels`中的基本OLS和2SLS回归。

如果你熟悉R语言,你可能想要使用`statsmodels`的[公式接口](https://www.statsmodels.org/dev/example_formulas.html),或考虑使用[r2py](https://rpy2.github.io/)在Python中调用R。
如果你熟悉R语言,你可以使用`statsmodels`的[公式接口](https://www.statsmodels.org/dev/example_formulas.html),或考虑使用[r2py](https://rpy2.github.io/)在Python中调用R。

## 练习

```{exercise}
:label: ols_ex1

在讲座中,我们认为原始模型存在内生性问题
在前面的讲座中,我们讨论了原始模型中的内生性问题。这个问题源于收入水平可能反过来影响制度的发展,从而导致估计结果产生偏差。

由于收入可能对制度发展产生影响而导致的偏差
虽然识别内生性问题最好是通过仔细分析数据和模型的经济含义,但我们也可以使用一个统计工具——**豪斯曼检验**来正式验证内生性的存在

虽然内生性最好通过思考数据和模型来识别,但我们可以使用**豪斯曼检验**来正式检验内生性
具体来说,我们要检验内生变量(制度质量指标$avexpr_i$)是否与回归方程的误差项$u_i$相关

我们要检验内生变量$avexpr_i$和误差项$u_i$之间是否存在相关性
如果存在相关性,就说明存在内生性问题

$$
\begin{aligned}
Expand Down Expand Up @@ -567,15 +565,13 @@ $$
y = X\beta + u
$$

为了求解未知参数 $\beta$,我们要最小化
残差平方和
为了求解未知参数 $\beta$,我们要最小化残差平方和

$$
\underset{\hat{\beta}}{\min} \hat{u}'\hat{u}
$$

重新整理第一个方程并代入第二个
方程,我们可以写成
重新整理第一个方程并代入第二个方程,我们可以写成

$$
\underset{\hat{\beta}}{\min} \ (Y - X\hat{\beta})' (Y - X\hat{\beta})
Expand Down
Loading