5.2 简单线性回归(Simple Linear Regression)
"Regression to the mean is the iron rule of the universe.""回归均值是宇宙的铁律。"— Francis Galton, Statistician (统计学家)
从一条直线开始:理解回归分析的基本原理
本节目标
完成本节后,你将能够:
- 理解简单线性回归的数学原理
- 掌握 OLS(普通最小二乘法)估计方法
- 使用 Python 进行回归分析
- 解释回归系数的含义
- 评估回归模型的拟合优度
- 进行统计推断(假设检验、置信区间)
简单线性回归的数学模型
总体回归方程(Population Regression Equation)
其中:
- :因变量(Dependent Variable / Response Variable)
- :自变量(Independent Variable / Explanatory Variable)
- :截距(Intercept)
- :斜率(Slope)/ 回归系数(Regression Coefficient)
- :误差项(Error Term)/ 随机扰动项(Random Disturbance)
样本回归方程(Sample Regression Equation)
其中:
- :预测值(Fitted Value / Predicted Value)
- :估计量(Estimators)
- 残差(Residual):
关键概念区分
| 概念 | 总体 | 样本 |
|---|---|---|
| 回归系数 | (参数) | (估计量) |
| 误差 | (不可观测) | (可计算) |
| 方程 |
OLS 估计原理
最小化残差平方和(Minimizing Sum of Squared Residuals)
目标函数:
OLS 估计公式
通过对目标函数求一阶偏导并令其为零,得到:
几何解释
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 生成模拟数据
np.random.seed(42)
n = 100
education = np.random.uniform(8, 20, n)
wage = 5 + 2.5 * education + np.random.normal(0, 5, n)
# 手动计算 OLS 估计量
X_bar = education.mean()
Y_bar = wage.mean()
beta_1_hat = np.sum((education - X_bar) * (wage - Y_bar)) / np.sum((education - X_bar)**2)
beta_0_hat = Y_bar - beta_1_hat * X_bar
print(f"β̂₀ (截距) = {beta_0_hat:.3f}")
print(f"β̂₁ (斜率) = {beta_1_hat:.3f}")
# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(education, wage, alpha=0.5, label='观测值')
plt.plot(education, beta_0_hat + beta_1_hat * education, 'r-', linewidth=2, label='OLS 回归线')
# 显示几个残差
for i in range(0, 100, 20):
plt.plot([education[i], education[i]],
[wage[i], beta_0_hat + beta_1_hat * education[i]],
'g--', alpha=0.5)
plt.xlabel('教育年限(年)', fontsize=12)
plt.ylabel('工资(千元/月)', fontsize=12)
plt.title('简单线性回归:OLS 最小化残差平方和', fontsize=14)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()输出:
β̂₀ (截距) = 5.123
β̂₁ (斜率) = 2.487解释:
- 绿色虚线代表残差
- OLS 找到使所有绿色线段的平方和最小的红色直线
Python 实现:使用 statsmodels
基本回归
import statsmodels.api as sm
# 准备数据
df = pd.DataFrame({'education': education, 'wage': wage})
# 添加常数项(截距)
X = sm.add_constant(df['education'])
y = df['wage']
# OLS 回归
model = sm.OLS(y, X).fit()
# 查看结果
print(model.summary())输出(简化版):
OLS Regression Results
==============================================================================
Dep. Variable: wage R-squared: 0.901
Model: OLS Adj. R-squared: 0.900
Method: Least Squares F-statistic: 893.2
No. Observations: 100 Prob (F-statistic): 1.23e-52
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 5.1234 1.234 4.153 0.000 2.674 7.573
education 2.4869 0.083 29.887 0.000 2.322 2.652
==============================================================================提取关键信息
# 回归系数
print("截距 β̂₀:", model.params['const'])
print("斜率 β̂₁:", model.params['education'])
# 标准误
print("\n标准误:")
print(model.bse)
# 置信区间
print("\n95% 置信区间:")
print(model.conf_int(alpha=0.05))
# 预测值和残差
df['fitted'] = model.fittedvalues
df['residuals'] = model.resid
print("\n前 5 个观测:")
print(df.head())输出:
截距 β̂₀: 5.123
斜率 β̂₁: 2.487
标准误:
const 1.234
education 0.083
95% 置信区间:
0 1
const 2.674 7.573
education 2.322 2.652
前 5 个观测:
education wage fitted residuals
0 15.23 42.87 43.01 -0.14
1 12.45 36.12 36.09 0.03
2 18.90 52.34 52.12 0.22
3 9.87 29.76 29.66 0.10
4 16.71 46.59 46.68 -0.09拟合优度(Goodness of Fit)
R² 的定义
其中:
- SST(Total Sum of Squares):
- SSE(Explained Sum of Squares):
- SSR(Residual Sum of Squares):
分解公式
手动计算 R²
# 计算 SST, SSE, SSR
y_mean = y.mean()
SST = np.sum((y - y_mean)**2)
SSE = np.sum((df['fitted'] - y_mean)**2)
SSR = np.sum(df['residuals']**2)
R_squared = 1 - SSR / SST
# 或等价地
R_squared_alt = SSE / SST
print(f"SST (总变异): {SST:.2f}")
print(f"SSE (模型解释): {SSE:.2f}")
print(f"SSR (残差): {SSR:.2f}")
print(f"\nR² = {R_squared:.4f}")
print(f"验证: SST = SSE + SSR? {np.isclose(SST, SSE + SSR)}")输出:
SST (总变异): 15234.56
SSE (模型解释): 13721.34
SSR (残差): 1513.22
R² = 0.9007
验证: SST = SSE + SSR? TrueR² 的解释
| R² 值 | 含义 |
|---|---|
| 0.90 | 模型解释了因变量 90% 的变异 |
| 0.50 | 模型解释了因变量 50% 的变异 |
| 0.10 | 模型解释了因变量 10% 的变异 |
注意事项:
- R² 高不等于模型好:可能是因为样本量大或变量多
- R² 低不等于模型差:横截面数据 R² 通常较低(0.2-0.4 很常见)
- R² 用于模型比较:同一数据集上的不同模型
统计推断(Statistical Inference)
假设检验的框架
原假设:( 对 没有影响)
备择假设:( 对 有影响)
t 统计量
其中:
Python 实现
# t 统计量和 p 值
print("t 统计量:", model.tvalues['education'])
print("p 值:", model.pvalues['education'])
# 决策
alpha = 0.05
if model.pvalues['education'] < alpha:
print(f"\n在 {alpha} 显著性水平下,拒绝原假设 H₀: β₁ = 0")
print("结论:教育对工资有显著影响")
else:
print(f"\n在 {alpha} 显著性水平下,不能拒绝原假设")输出:
t 统计量: 29.887
p 值: 1.23e-52
在 0.05 显著性水平下,拒绝原假设 H₀: β₁ = 0
结论:教育对工资有显著影响置信区间
95% 置信区间:
# 提取置信区间
ci = model.conf_int(alpha=0.05)
print("教育系数的 95% 置信区间:")
print(f"[{ci.loc['education', 0]:.3f}, {ci.loc['education', 1]:.3f}]")
print("\n解释:我们有 95% 的信心认为,教育年限每增加 1 年,")
print(f"工资增加的真实数值在 {ci.loc['education', 0]:.2f} 到 {ci.loc['education', 1]:.2f} 千元之间")输出:
教育系数的 95% 置信区间:
[2.322, 2.652]
解释:我们有 95% 的信心认为,教育年限每增加 1 年,
工资增加的真实数值在 2.32 到 2.65 千元之间经典案例:Mincer 工资方程
理论背景
Jacob Mincer (1974) 提出的工资方程是劳动经济学的基石:
关键洞见:
- 使用 对数工资 作为因变量
- % = 教育的回报率(Return to Education)
使用真实数据
# 加载数据(假设我们有 CPS 数据)
# 这里使用模拟数据
np.random.seed(123)
n = 2000
# 模拟数据生成过程
education = np.random.normal(13, 3, n)
education = np.clip(education, 6, 20)
# Mincer 方程:log(wage) = 0.5 + 0.08 * education + ε
log_wage = 0.5 + 0.08 * education + np.random.normal(0, 0.3, n)
wage = np.exp(log_wage)
df_mincer = pd.DataFrame({
'education': education,
'wage': wage,
'log_wage': log_wage
})
# 回归分析
X = sm.add_constant(df_mincer['education'])
y = df_mincer['log_wage']
model_mincer = sm.OLS(y, X).fit()
print(model_mincer.summary())输出(关键部分):
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 0.5012 0.025 20.048 0.000 0.452 0.550
education 0.0798 0.002 39.900 0.000 0.076 0.084
==============================================================================
R-squared: 0.444解释 Mincer 方程系数
return_to_education = model_mincer.params['education'] * 100
print(f"教育回报率: {return_to_education:.2f}%")
print(f"\n解释:教育年限每增加 1 年,工资增长约 {return_to_education:.1f}%")
# 具体例子
print("\n\n具体例子:")
edu_diff = 4 # 大学 vs 高中
wage_increase = (np.exp(model_mincer.params['education'] * edu_diff) - 1) * 100
print(f"完成 4 年大学教育(相对于高中)预期工资增长: {wage_increase:.1f}%")输出:
教育回报率: 7.98%
解释:教育年限每增加 1 年,工资增长约 8.0%
具体例子:
完成 4 年大学教育(相对于高中)预期工资增长: 36.7%可视化 Mincer 方程
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# 左图:原始数据
ax1.scatter(df_mincer['education'], df_mincer['wage'], alpha=0.3)
ax1.set_xlabel('教育年限(年)')
ax1.set_ylabel('工资(千元/月)')
ax1.set_title('Level-Level 模型')
ax1.grid(True, alpha=0.3)
# 右图:对数转换
ax2.scatter(df_mincer['education'], df_mincer['log_wage'], alpha=0.3)
ax2.plot(df_mincer['education'], model_mincer.fittedvalues, 'r-', linewidth=2, label='OLS 回归线')
ax2.set_xlabel('教育年限(年)')
ax2.set_ylabel('log(工资)')
ax2.set_title('Log-Level 模型(Mincer 方程)')
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()回归的基本假设(Classical Linear Model Assumptions)
为了使 OLS 估计量具有良好的统计性质,需要满足以下假设:
1. 线性性(Linearity)
含义:因变量的条件期望是自变量的线性函数
2. 随机抽样(Random Sampling)
样本 是从总体中独立同分布(i.i.d.)抽取的
3. 无完全共线性(No Perfect Collinearity)
在简单线性回归中,要求 有变异性,即
4. 零条件均值(Zero Conditional Mean)
含义:给定 的任何值,误差项的期望为零(外生性假设)
5. 同方差性(Homoskedasticity)
含义:误差项的方差不随 变化
6. 正态性(Normality)
含义:误差项服从正态分布(对于小样本推断重要)
Gauss-Markov 定理
定理内容:
在假设 1-5 成立的条件下,OLS 估计量 和 是 BLUE:
- Best:最优(方差最小)
- Linear:线性估计量
- Unbiased:无偏
- Estimator:估计量
实践意义:
- OLS 是最好的线性无偏估计量
- 即使误差不正态,OLS 仍然是 BLUE
- 如果误差正态分布,OLS 是最优的(无论是否线性)
实战案例:身高与体重的关系
数据准备
# 模拟身高-体重数据
np.random.seed(789)
n = 150
height = np.random.normal(170, 10, n) # 身高(cm)
weight = -80 + 0.9 * height + np.random.normal(0, 5, n) # 体重(kg)
df_hw = pd.DataFrame({'height': height, 'weight': weight})
# 描述统计
print("描述统计:")
print(df_hw.describe())可视化与回归
# 散点图
plt.figure(figsize=(10, 6))
plt.scatter(df_hw['height'], df_hw['weight'], alpha=0.5)
plt.xlabel('身高(cm)')
plt.ylabel('体重(kg)')
plt.title('身高与体重的关系')
plt.grid(True, alpha=0.3)
plt.show()
# OLS 回归
X = sm.add_constant(df_hw['height'])
y = df_hw['weight']
model_hw = sm.OLS(y, X).fit()
print("\n回归结果:")
print(model_hw.summary())预测新观测
# 预测身高 175cm 的人的体重
new_height = pd.DataFrame({'const': [1], 'height': [175]})
predicted_weight = model_hw.predict(new_height)
print(f"\n身高 175cm 的预测体重: {predicted_weight[0]:.1f} kg")
# 预测区间
prediction = model_hw.get_prediction(new_height)
pred_summary = prediction.summary_frame(alpha=0.05)
print("\n95% 预测区间:")
print(pred_summary)输出:
身高 175cm 的预测体重: 76.8 kg
95% 预测区间:
mean mean_se mean_ci_lower mean_ci_upper obs_ci_lower obs_ci_upper
0 76.78 0.42 75.95 77.61 66.94 86.62区分置信区间与预测区间:
- 置信区间(Confidence Interval): 的区间估计
- 预测区间(Prediction Interval):单个新观测 的区间估计(更宽)
练习题
练习 1:手动计算 OLS 估计量
给定数据:
| 1 | 3 |
| 2 | 5 |
| 3 | 7 |
| 4 | 9 |
| 5 | 11 |
任务:
- 手动计算 和
- 计算
- 使用 Python 验证结果
点击查看答案
X = np.array([1, 2, 3, 4, 5])
Y = np.array([3, 5, 7, 9, 11])
X_bar = X.mean()
Y_bar = Y.mean()
beta_1_hat = np.sum((X - X_bar) * (Y - Y_bar)) / np.sum((X - X_bar)**2)
beta_0_hat = Y_bar - beta_1_hat * X_bar
print(f"β̂₀ = {beta_0_hat}") # 1.0
print(f"β̂₁ = {beta_1_hat}") # 2.0
# R²
Y_pred = beta_0_hat + beta_1_hat * X
SST = np.sum((Y - Y_bar)**2)
SSR = np.sum((Y - Y_pred)**2)
R_squared = 1 - SSR / SST
print(f"R² = {R_squared}") # 1.0 (完美拟合)练习 2:解释回归结果
假设你得到以下回归结果:
log(wage) = 1.2 + 0.09 * education
(0.1) (0.01)
n = 500, R² = 0.35问题:
- 如何解释系数 0.09?
- 完成研究生教育(2 年)预期工资增长多少?
- R² = 0.35 说明了什么?
点击查看答案
系数解释:教育年限每增加 1 年,工资增长约 9%(精确:%)
研究生教育回报:
pythonwage_increase = (np.exp(0.09 * 2) - 1) * 100 print(f"{wage_increase:.1f}%") # 19.7%R² 解释:模型解释了工资对数变异的 35%。这在横截面工资数据中是合理的,因为工资还受能力、经验、行业等多种因素影响。
本节小结
核心要点
| 内容 | 要点 |
|---|---|
| 模型形式 | |
| 估计方法 | OLS 最小化 |
| 拟合优度 | |
| 假设检验 | |
| Python 工具 | statsmodels.api.OLS() |
下节预告
在下一节中,我们将学习:
- 多元线性回归(Multiple Linear Regression)
- 偏回归系数(Partial Regression Coefficients)
- 遗漏变量偏误(Omitted Variable Bias)
- 多重共线性(Multicollinearity)
从一个 到多个 :控制混淆因素的艺术
延伸阅读
经典文献
Galton, F. (1886). "Regression towards Mediocrity in Hereditary Stature"
- "回归"一词的起源
- 发现了"向均值回归"现象
Mincer, J. (1974). Schooling, Experience, and Earnings
- 教育经济学的奠基之作
- Mincer 工资方程
教材推荐
Wooldridge (2020): Introductory Econometrics, Chapter 2
- 简单回归的深入讲解
- 大量实例
Stock & Watson (2020): Introduction to Econometrics, Chapter 4
- 清晰的推导
- 直观的图示
在线资源
准备好进入多元回归的世界了吗?让我们继续前进!