4. 半参数模型 (Semi-parametric Model)
半参数模型结合了参数化和非参数化的方法。可以在整体上采用线性回归,但在局部允许非线性变化。这样做的目的是在保持模型的线性解释性的同时,捕捉细微的弧度趋势。
例如,可以定义:
y = β 0 + β 1 x + g ( x ) + ϵ y = \beta_0 + \beta_1 x + g(x) + \epsilon y=β0+β1x+g(x)+ϵ
其中 g ( x ) g(x) g(x) 是一个非参数化函数,例如平滑样条,可以捕捉数据的局部弧度。
- 优点:与 GAM 类似,保持模型解释性的同时捕捉非线性。
- 缺点:需要选择合适的非参数函数形式,可能较复杂。
半参数模型结合了线性成分和非线性成分,既可以捕捉数据中的线性趋势,也可以处理局部的非线性变化。在 Python 中,我们可以使用 statsmodels
中的 GLM
(广义线性模型)和样条函数来实现半参数模型。这种方法既保持了全局的线性趋势,又允许局部的平滑变化。
以下是一个半参数模型的 Python 示例。代码会生成数据、拟合半参数模型,并绘制数据散点、回归线以及置信区间。
代码示例
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.gam.api import GLMGam, BSplines
from patsy import dmatrix# 生成带有线性和非线性成分的样本数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y = 1.5 * x + 0.5 * np.sin(x * 1.5) + np.random.normal(0, 0.5, size=x.shape)# 重新调整形状以适应 statsmodels 的输入格式
X = sm.add_constant(x) # 添加常数项
X_spline = dmatrix("bs(x, df=5, degree=3)", {"x": x}, return_type='dataframe') # 样条基函数# 使用 statsmodels 构建半参数模型
model = GLMGam(y, exog=X, smoother=BSplines(x[:, None], df=[5], degree=[3]))
result = model.fit()# 预测和计算置信区间
x_pred = np.linspace(0, 10, 100)
X_pred = sm.add_constant(x_pred)
X_spline_pred = dmatrix("bs(x_pred, df=5, degree=3)", {"x_pred": x_pred}, return_type='dataframe')
y_pred = result.predict(exog=X_pred, exog_smooth=X_spline_pred)# 使用 Bootstrap 计算置信区间
n_bootstraps = 200
y_pred_bootstrap = []for _ in range(n_bootstraps):# 随机采样并拟合模型sample_indices = np.random.choice(len(x), len(x), replace=True)X_sample = X[sample_indices]X_spline_sample = X_spline.iloc[sample_indices]y_sample = y[sample_indices]model_sample = GLMGam(y_sample, exog=X_sample, smoother=BSplines(x[sample_indices][:, None], df=[5], degree=[3]))result_sample = model_sample.fit()y_pred_sample = result_sample.predict(exog=X_pred, exog_smooth=X_spline_pred)y_pred_bootstrap.append(y_pred_sample)# 将预测结果转换为数组
y_pred_bootstrap = np.array(y_pred_bootstrap)# 计算置信区间
lower_bound = np.percentile(y_pred_bootstrap, 2.5, axis=0)
upper_bound = np.percentile(y_pred_bootstrap, 97.5, axis=0)# 绘制散点图、回归曲线和置信区间
plt.figure(figsize=(10, 6))
plt.scatter(x, y, color='gray', label='Data Points')
plt.plot(x_pred, y_pred, color='blue', label='Semi-parametric Model')
plt.fill_between(x_pred, lower_bound, upper_bound, color='lightblue', alpha=0.5, label='95% Confidence Interval')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Semi-parametric Model with 95% Confidence Interval')
plt.legend()
plt.show()
代码说明
- 数据生成:创建含有线性趋势和轻微非线性成分的数据,公式为 y = 1.5 x + 0.5 sin ( 1.5 x ) + noise y = 1.5x + 0.5\sin(1.5x) + \text{noise} y=1.5x+0.5sin(1.5x)+noise。
- 构建半参数模型:
- 线性部分:使用
statsmodels
的GLMGam
构建一个广义加性模型(GAM),其中exog
包含线性成分 X X X。 - 非线性部分:通过样条基函数(B样条)
BSplines
添加非线性成分,使模型能够捕捉局部的非线性变化。
- 线性部分:使用
- 模型拟合与预测:使用拟合后的模型对生成的数据进行预测,并获取预测结果。
- 置信区间计算:使用 Bootstrap 方法生成 200 组不同的样本集,拟合并预测得到的回归曲线,并计算 2.5% 和 97.5% 百分位数,作为 95% 的置信区间。
- 绘图:绘制数据散点、回归曲线和置信区间。
输出图形
运行代码后生成以下内容:
- 灰色散点图:显示原始数据点。
- 蓝色回归曲线:显示半参数模型拟合的回归线,结合了线性和非线性成分。
- 淡蓝色置信区间:展示了通过 Bootstrap 生成的 95% 置信区间,反映了模型在不同 x 值上的置信范围。