/ / /
第14讲:回归模型不稳定性 (Regression Model Instability)
🔴
入学要求
💯
能力测试
🛣️
课程安排
🕹️
研究资源

第14讲:回归模型不稳定性 (Regression Model Instability)

💡

查看全集:💎Quantopia量化分析56讲

1. 回归不稳定性简介

回归模型帮助我们理解变量之间的关系,但由于多种因素,其系数可能不稳定。本教程探讨三个主要原因:小样本偏差噪声、结构突变和多重共线性。


2. 小样本中的偏差噪声

核心概念

在小数据集中,随机噪声可能对回归系数产生不成比例的影响。随着样本量增大,系数会趋于稳定。

示例:随机噪声回归

import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt

def linreg(X, Y):
    X = sm.add_constant(X)  # 添加截距项
    model = sm.OLS(Y, X).fit()
    return model.params[0], model.params[1]  # 截距, 斜率

# 生成20个随机数据点
np.random.seed(107)
small_data = np.random.randn(20)
xs_small = np.arange(20)
a, b = linreg(xs_small, small_data)

# 可视化
plt.scatter(xs_small, small_data, alpha=0.7)
plt.plot(xs_small, xs_small*b + a, 'r')
plt.title("小样本回归演示");

练习1

生成1000个随机点观察系数变化:

large_data = np.random.randn(1000)
xs_large = np.arange(1000)
a_large, b_large = linreg(xs_large, large_data)
print(f"大样本斜率:{b_large:.4f}")

3. 结构突变(机制变化)

核心概念

当变量间关系发生突变时,模型在突变前后会失效。

示例:SPY价格结构突变

import yfinance as yf

# 获取数据
data = yf.download('SPY', start='2003-01-01', end='2009-02-01')
prices = data['Close']

# 设置断点(约2007年6月)
breakpoint = 1200
pre_break = prices.iloc[:breakpoint]
post_break = prices.iloc[breakpoint:]

# 分段回归
X_full = np.arange(len(prices))
a_full, b_full = linreg(X_full, prices)

X_pre = np.arange(len(pre_break))
a_pre, b_pre = linreg(X_pre, pre_break)

X_post = np.arange(len(post_break))
a_post, b_post = linreg(X_post, post_break)

# 可视化
plt.figure(figsize=(10,6))
prices.plot(label='SPY价格')
plt.plot(prices.index, X_full*b_full + a_full, 'y', label='全段回归')
plt.plot(pre_break.index, X_pre*b_pre + a_pre, 'r', label='断点前')
plt.plot(post_break.index, X_post*b_post + a_post, 'r', label='断点后')
plt.legend();

练习2

使用CUSUM检验结构突变:

from statsmodels.stats.diagnostic import breaks_cusumolsresid

full_model = sm.OLS(prices, sm.add_constant(X_full)).fit()
print(f"CUSUM检验p值:{breaks_cusumolsresid(full_model.resid)[1]:.2e}")

4. 多重共线性问题

核心概念

当预测变量高度相关时,微小数据变化会导致系数大幅波动。

示例:相关ETF分析

# 获取三组数据
data = yf.download(['SPY', 'MDY', 'V'], start='2013-01-01', end='2015-06-01')['Close']

# 数据清洗
b1 = data['SPY'].dropna()
b2 = data['MDY'].dropna()
asset = data['V'].dropna()

# 计算相关系数
corr = b1.corr(b2)
print(f"SPY-MDY相关系数:{corr:.2f}")

# 多元回归函数
def multiple_linreg(Y, X1, X2):
    X = sm.add_constant(np.column_stack((X1, X2)))
    model = sm.OLS(Y, X).fit()
    return model.params

# 分时段回归
params1 = multiple_linreg(asset['2013':'2015'], b1['2013':'2015'], b2['2013':'2015'])
params2 = multiple_linreg(asset, b1, b2)

print(f"2013-2015年系数:SPY={params1[1]:.2f}, MDY={params1[2]:.2f}")
print(f"延长时段系数:SPY={params2[1]:.2f}, MDY={params2[2]:.2f}")

练习3

计算方差膨胀因子(VIF):

from statsmodels.stats.outliers_influence import variance_inflation_factor

X = sm.add_constant(np.column_stack((b1, b2)))
vifs = [variance_inflation_factor(X, i) for i in range(1, X.shape[1])]
print(f"方差膨胀因子:{vifs}")

5. 解决方案


6. 关键要点

  1. 样本容量直接影响模型稳定性
  1. 警惕时间序列中的结构突变
  1. 检查预测变量间的相关性
  1. 使用统计检验验证模型假设

下一步建议:探索岭回归/Lasso回归等正则化方法,学习时间序列交叉验证技巧。

附:练习合集