# 生成示例数据(故意制造斜率突变)
set.seed(123)
x <- seq(0, 10, length.out=100)
y <- c(0.5*x[x<=5] + rnorm(50, sd=0.3),
2*(x[x>5]-5) + 2.5 + rnorm(50, sd=0.3))
# 拟合LOESS(局部加权回归)
loess_fit <- loess(y ~ x, span=0.3) # span越小,越贴近局部数据
pred_loess <- predict(loess_fit)
# 绘制结果
plot(x, y, main="LOESS vs 分段直线", col="gray")
lines(x[x<=5], 0.5*x[x<=5], col="blue", lwd=2) # 真实分段1
lines(x[x>5], 2*(x[x>5]-5)+2.5, col="blue", lwd=2) # 真实分段2
lines(x, pred_loess, col="red", lwd=2, lty=2) # LOESS拟合
legend("topleft", legend=c("真实分段", "LOESS拟合"), col=c("blue", "red"), lty=1:2).
局部回归的工作原理
可以想象,局部回归是在每个数据点上“聚焦”:
- 选择一个点:比如,我们要预测处的值。
- 选取邻近数据:它会找到附近的一组数据点。
- 赋予权重:它不会平等地对待这些点,而是给距离越近的点赋予更高的权重,距离越远的点权重越低。常用的权重函数会使得距离较远的点权重几乎为零。
- 加权回归:它使用这些带有权重的邻近点,拟合一个简单的模型(比如一条直线或二次曲线)。这个模型不是为了预测整个数据集,而仅仅是为了得到处的预测值。
- 移动焦点:然后,算法会移动到下一个点,重复上述步骤,得到的预测值。
这个过程会为数据集中的每个点都生成一个局部预测值。
为什么结果会是光滑的?
你提出的“如果每个直线斜率差异很大,不就不能光滑吗”这个问题非常敏锐,这正是局部回归设计的巧妙之处。
答案在于加权和连续性。
- 平滑过渡:当局部回归的“焦点”从一个点移动到下一个点时,加权函数在其中起到了关键作用。它使得每个点附近的模型都与它邻近点的模型有重叠和连续性。你可以把这想象成水墨画的晕染效果,而不是硬生生的边界。当算法从移动到时,用于拟合的加权数据集与用于的加权数据集大部分是重叠的,只是权重略有变化。因此,拟合出来的模型也是平滑过渡的。
- 不硬性分段:分段回归会把数据硬性地分为几个区段,每个区段拟合一条独立的直线。这些直线在连接处(断点)的斜率差异可能很大,看起来就不平滑。而局部回归没有“断点”,它是一个连续移动的过程,因此没有突兀的转折。
所以,局部回归不是简单的“滑动拟合多条直线”,而是通过加权和连续的局部拟合过程,最终形成一条能够平滑反映数据整体趋势的曲线。