一、残差定义#
线性回归的基本形式:
残差 = 观测值 - 预测值
其中:
-
是第i个观测值的残差
-
是第i个观测值的实际值
-
是第i个观测值的预测值
残差项的三个重要假设:
-
线性关系:Y与X之间存在线性关系
-
同方差性:误差项具有相同的方差
-
独立同分布:误差项相互独立且服从相同的分布
二、残差诊断三步法#
2.1 线性关系检验#
code
# 生成非线性数据示例
n = 50
X = np.linspace(0, 10, n)
Y = 2*X + 3*np.sin(X) + np.random.normal(0, 1, n)
model = sm.OLS(Y, sm.add_constant(X)).fit()
plt.scatter(model.predict(), model.resid)
plt.axhline(0, color='r', linestyle='--')当残差呈现规律性分布时(如抛物线型),提示可能存在非线性关系。
2.2 异方差性检验#
Breusch-Pagan检验实现:
code
bp_test = smd.het_breuschpagan(residuals, model.model.exog)
print(f"P值:{bp_test[1]:.4f}")
if bp_test[1] < 0.05:
print("存在异方差性")
else:
print("满足同方差假设")处理方法对比表:
| 方法 | 适用场景 | 注意事项 |
|---|---|---|
| 差分法 | 时间序列数据 | 改变数据维度 |
| 对数变换 | 正数数据 | 解释系数需逆变换 |
| Box-Cox变换 | 非正态分布数据 | λ参数需优化选择 |
2.3 自相关检验#
Ljung-Box检验示例:
code
lb_test = smd.acorr_ljungbox(residuals, lags=10)
print(f"最大P值:{lb_test[1].max():.4f}")
if any(lb_test[1] < 0.05):
print("存在自相关")
else:
print("无显著自相关")实战案例:特斯拉β系数计算#
数据获取与处理#
code
import yfinance as yf
# 获取数据
start = '2020-01-01'
end = '2021-01-01'
tsla = yf.download('TSLA', start=start, end=end)['Close']
spy = yf.download('SPY', start=start, end=end)['Close']
# 计算收益率
returns = pd.DataFrame({
'TSLA': tsla.pct_change().dropna(),
'SPY': spy.pct_change().dropna()
})回归分析与诊断#
code
# 回归模型
X = sm.add_constant(returns['SPY'])
model = sm.OLS(returns['TSLA'], X).fit()
# 残差诊断图
fig, axes = plt.subplots(1,2, figsize=(12,5))
axes[0].scatter(model.predict(), model.resid)
axes[0].axhline(0, color='r')
axes[1].plot(model.resid)综合检验#
code
# 异方差检验
bp_test = smd.het_breuschpagan(model.resid, model.model.exog)
print(f"异方差检验P值:{bp_test[1]:.4f}")
# 自相关检验
lb_test = smd.acorr_ljungbox(model.resid, lags=5)
print(f"自相关检验P值:{lb_test[1][-1]:.4f}")练习与思考#
-
尝试对SPY收益率进行平方变换后重新回归,观察残差变化
-
将时间周期改为3年,比较β系数的稳定性
-
在模型中添加NASDAQ指数作为第二个解释变量,分析模型改进效果
关键提示:当使用Box-Cox变换时,注意数据必须为正数,可使用公式:
这是Box-Cox变换的数学表达式,其中:
y 是原始数据
λ (lambda) 是变换参数
当 λ = 0 时,变换等价于取自然对数
当 λ ≠ 0 时,使用 (y^λ - 1)/λ 进行变换
通过系统性的残差分析,可以有效验证模型假设,提升回归结果的可靠性。建议每次建立回归模型后,至少进行残差图的视觉检查和基本的统计检验。