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 值上的置信范围。