用一条直线去拟合会弯曲的数据,注定行不通。
线性回归假定自变量与目标变量之间的关系是直线。不幸的是,大多数现实世界中的关系并非如此。想想收入与支出、时间与增长之间的关系——它们会弯折、变平、再度弯折,并以单一斜率无法表达的方式改变方向。
样条回归的做法是让关系在需要的地方“弯”,同时避免拟合出无约束的狂野曲线。思路是在整个自变量范围内拟合多个平滑的多项式片段,并在特定点将它们衔接起来。
本文将带您理解样条回归的核心概念、结如何控制灵活性、主要样条类型,以及如何在实践中应用。
在学习样条之前,先阅读我们的教程,它将教会您有关 简单线性回归 的一切。
什么是样条回归?
样条回归是一种用分段多项式函数来建模非线性关系的回归技术,这些分段在称为“结”的特定点处连接在一起。
因此,样条回归并非用一个方程描述整个关系,而是将自变量范围切分成较小的区间,并在每个区间上分别拟合多项式。这些片段在结处相接,约束条件确保过渡平滑。
最终效果介于两种极端之间。它比线性回归更灵活,后者只能用一条直线贯穿数据;它又比完全无约束的非线性模型(如深度神经网络或核方法)更有结构,后者几乎能拟合任何东西,却很难告诉您它们究竟拟合了什么。
正因如此,样条在应用统计中极为常见。
为什么需要样条回归
真实数据几乎从不沿直线变化。
线性回归常作为建模关系的默认起点,但它有个强假设:自变量对结果的影响在全范围内保持不变。当真实关系弯曲或改变方向时,直线会欠拟合。在极端处误差加大,模型难以跟随模式。
补救办法是使用更灵活的模型。高次多项式回归是一个选项——添加 x^2、x^3、x^4 等项,直到曲线能足够弯曲以匹配数据。但当数据边缘点较少时,多项式会在边界处剧烈上扬或下沉,变得不稳定。这种行为称为 Runge 现象,使高次多项式在预测上存在风险。
样条回归位于这两种极端之间。
您可以在数据弯曲的地方获得局部灵活性,而不会出现单个高次多项式的整体不稳定。每个片段都是低次多项式(通常为三次),因此任何单独部分都不至于表现异常。并且由于这些片段在结处平滑连接,整体曲线仍像是一个连续函数。
简而言之,样条既有足够的灵活性来追随复杂模式,又有足够的结构在边界处保持稳健。
样条回归如何工作
样条回归通常遵循三个简单步骤。
将自变量范围划分为区域: 在自变量轴上选择一组结。这些结将范围划分为若干区间。放置三个结会得到四个区域。结是片段之间的边界。
在每个区域内拟合多项式: 在每个区间内,模型拟合一个低次多项式。每个区域都有自己的多项式系数,因此曲线可以在自变量范围的不同部分以不同方式弯曲。关系几乎平坦的区域会得到近乎平坦的多项式;关系急剧弯曲的区域会得到更弯的多项式。
连接各区域: 模型在每个结处施加连续性约束。结两侧的多项式值必须相等,避免曲线跳变。对于三次样条,一阶与二阶导数也必须相等,这意味着没有尖角,也没有曲率的突然变化。
正是这些约束,让样条看起来像一条整体平滑的曲线:局部弯折,但在整个自变量范围内连续流畅。视觉上,您看不出一个多项式在哪里结束、下一个从哪里开始。
结、 多项式阶数与连续性约束共同定义了样条。改变其中任意一个,都会得到具有不同性质的样条——接下来的部分将具体介绍。
样条回归中的结是什么?
结是自变量轴上一个多项式片段结束、下一个片段开始的点。
可以把它们看作样条的“关节”。若在 x = 5 处放置一个结,模型会在小于 5 的取值范围拟合一个多项式,在大于 5 的范围拟合另一个多项式。两者在结处相接,连续性约束确保平滑连接。增加更多结就会得到更多片段,也就意味着曲线能在更多位置弯折。
因此,结是控制模型灵活性的主要杠杆。
结的数量决定样条由多少个独立的多项式片段组成;结的位置决定曲线被允许在何处改变形状。只有两个结的样条只能在少数位置弯折;有二十个结的样条几乎可以跟随每一个数据点。
因此,选择合适的结的数量与位置,是样条回归中的关键决策。
结太少
如果结放得太少,样条的片段不足以跟随数据中的真实模式,曲线会过于僵硬。它几乎表现得像一个低次多项式——整体上有些灵活,但无法捕捉局部变化。
设想用一个结的样条去拟合具有三个明显阶段的数据:上升、平台和下降。只有一个结时,样条只有两个片段可用。它可以捕捉上升阶段和另一个阶段,但无法同时覆盖三者。结果与线性回归相同——在样条无法匹配数据形状的地方产生误差。
结太少示例
结太少会导致欠拟合。模型过于平滑,难以有效。
结太多
相反的问题同样糟糕。结放得太多时,样条片段太多,开始拟合数据中的噪声而非真实模式。曲线在每个观测之间来回摆动,追逐随机波动而不是潜在趋势。
在仅有 50 个样本的数据上放置 20 个结的样条,看起来更像“连点成线”的涂鸦而不是模型。它几乎能完美拟合训练数据,但对新数据的预测不可靠。输入的微小变化会引起输出的巨大且不可预测的变化。
结太多示例
结太多会导致过拟合。模型过于灵活,难以泛化。
理想状态是:结的数量足以捕捉数据中的真实弯折,但又不至于让模型开始记忆噪声。下面的内容将介绍如何在实践中作出这样的权衡。
样条的类型
样条有几种不同“口味”,选择主要取决于每个片段使用何种多项式,以及对曲线施加了哪些约束。
线性样条
线性样条是最简单的版本。每个片段都是一条直线,片段在结处连接。
线性样条示例
此处的连续性约束较宽松:结两侧的函数值必须相等,但斜率可以变化。结果看起来像一系列相连的线段,每个结处都有拐角。它足以处理简单的弯折,但曲线有时不够平滑。
当您只关心整体趋势且不在意视觉上的尖锐感时,线性样条很合适。它们也最易解释,因为每个片段都只是具有自身斜率的直线。
三次样条
三次样条是大多数应用中的默认选择。每个片段都是三次多项式(3 次),且其连续性约束比线性样条更严格。
三次样条示例
在每个结处需满足三项条件:函数值相等、一阶导数相等、二阶导数相等。这意味着没有跳变、没有尖角、没有曲率的突变。曲线穿过结点时流畅自然,视觉上看不出过渡发生的位置。
三次是允许平滑曲率变化的最低多项式次数,因此十分流行。更高次数很少带来有用的灵活性,反而使模型更难控制。
自然三次样条
自然三次样条是在数据边界处增加额外约束的变体。
自然三次样条示例
常规三次样条在边缘可能表现异常,尤其是在数据点稀少的地方。最左和最右的片段仍是三次多项式,而三次多项式在外推时可能迅速上扬或下沉。
自然三次样条通过强制边界结处的二阶导数为零来规避这一问题。实践中,这意味着在最外侧结之外,曲线变为线性。外推行为更稳定,因此当您关心靠近数据边界的预测时,自然三次样条更合适。
B-样条
B-样条(basis splines,基样条)是构造样条的另一种方式。它不是直接定义每个多项式片段,而是将样条表示为一组基函数的加权和。
B-样条示例
每个基函数本身就是一个在有限区域内非零的小样条。完整的样条是这些基函数的总和,每个基函数乘以一个由回归估计出的系数。
B-样条数值稳定且易于扩展。Python 与 R 中的大多数现代样条实现都使用 B-样条表示,即便用户接口看起来像常规样条。如果您曾在 R 中调用 bs() 或在 scikit-learn 中使用 SplineTransformer,那您用的就是 B-样条。
样条回归 vs 多项式回归
多项式回归与样条回归都能处理非线性关系,但方法截然不同,差异在于曲线如何构建。
多项式回归
多项式回归 在整个自变量范围上拟合单个全局多项式。您选一个次数(2、3、5、10),模型找到一组系数,以最小化全部数据上的误差。曲线由一个方程描述,并在任何位置都遵循这个方程。
听起来很干净,但有问题。单个多项式必须在整个范围内平衡拟合效果,因此某一区域发生的事会影响所有其他区域。若为处理中部的急剧弯折而提高次数,曲线会在边界处开始摆动。这就是前面提到的 Runge 现象——高次多项式在数据边界附近变得不稳定。
另一个问题是多项式回归没有“局部性”概念。在 x = 5 处出现的尖峰可能会改变 x = 50 的拟合形状,因为每个观测都作用于同一个全局方程。
样条回归
样条回归把自变量范围分成多个片段,并在每个片段上拟合低次多项式。多项式在结处平滑连接,但彼此相对独立,其形状主要由各自区域内的数据驱动。
这带来局部灵活性。弯折明显的区域得到更弯的多项式;趋势平坦的区域得到近乎平坦的多项式。且由于每个片段都是低次(通常三次),任何单独部分在极端处都不太可能表现怪异。尤其在数据边界附近,您会获得更平滑、更稳定的拟合。
并排比较
多项式与样条回归对比
因此,如果关系只有轻微非线性且您能接受全局拟合,多项式回归可行;若模式更复杂或您关心边界附近的预测,样条更稳妥。
选择结的数量与位置
结的选择是样条回归中最重要的部分。结太少会欠拟合,太多会过拟合;而放置位置也会改变模型能捕捉到哪些模式。
有几种方法,实际中通常会组合使用:
领域知识: 若了解问题背景,请加以利用。临床研究可能在已知的临床阈值处放置结;定价模型可能在消费者行为预计会改变的点放置结。基于领域的结位选择最易解释,因为片段对应真实边界。
等距结: 选定结的数量,并在自变量范围上均匀放置。当数据在自变量轴上大致均匀分布时,这种方法可行;但若某些区域密集、另一些稀疏,则不适用——等距结可能落在数据几乎没有的区域,导致拟合不稳定。
基于分位数的结: 不按 x 轴等距放置,而是在自变量的分位数处放置结。若有 4 个结,则放在第 20、40、60、80 百分位。这样可确保每个片段包含大致相同数量的观测,使在稀疏区域的拟合更可靠。
交叉验证: 试验不同的结数,为每种情况拟合样条,并比较留出数据上的表现。验证误差最低的配置为优。这样可消除拍脑袋决策,但增加计算成本,且结果仍取决于您搜索的放置策略(等距或分位)。
权衡与所有回归问题相同:灵活性与复杂度。更多结意味着更灵活,能跟随更细的模式,也更可能追逐噪声;更少结意味着更稳定、更易解释,但可能错过真实模式。
可以从将 3–5 个结放在分位数位置开始,然后检查残差。如果残差显示出样条未捕捉到的系统性模式,就在该区域增加一个结;如果拟合看起来过于“抖动”,就减掉一个。若需要为选择辩护或模型将投入生产,建议使用交叉验证。
样条回归在机器学习与统计中的应用
凡是需要在不预设具体函数形式的前提下建模平滑的非线性效应,都会看到样条的身影。常见领域包括:
时间序列趋势: 常见用途是将时间序列中的平滑趋势与短期波动分离。以时间为自变量拟合样条,可得到灵活的趋势线,既能适应方向变化,又不至于对噪声过度反应。经济学家与分析师经常用它来描述变量的底层轨迹——如 GDP 或股价——而无需假定线性或指数形式。
经济学与计量经济学: 当变量的影响在其取值范围内发生变化时,样条可用于建模这种关系。收入对消费的影响并非常数,低收入家庭与高收入家庭的支出行为不同。样条无需预设函数形式即可揭示这些差异。
医疗与生物统计: 许多健康结局与年龄、BMI、血压或生物标志物等自变量之间存在非线性关系。疾病风险常呈 U 形或 J 形——两端风险高,中间安全。线性模型会忽略这一点。三次样条与自然三次样条是建模这些效应的标准工具,并已内置于大多数临床研究常用的统计软件中。
环境与生态建模: 在建模物种或气候变量对环境梯度的响应时也常见样条。如温度、海拔、降雨量等常对物种丰度或作物产量产生非线性影响。样条让研究者得以在不事先设定形状的前提下拟合响应曲线。
在这些场景中,样条在需要时提供灵活性,同时无需猜测关系的函数形式。这使其既适合探索性建模,也适合作为强调可解释性的生产模型。
Python 中的样条回归
Python 有三种常用方式拟合样条回归:scikit-learn(面向 ML 流水线)、patsy(基于公式的模型指定)与 statsmodels(统计推断)。下面逐一介绍。
使用 scikit-learn
scikit-learn 提供 SplineTransformer,可将数值特征转换为一组 B-样条基函数,然后将这些特征输入任意线性回归模型。
import numpy as np
from sklearn. linear_model import LinearRegression
from sklearn. preprocessing import SplineTransformer
from sklearn. pipeline import make_pipeline
np. random. seed( 42 )
x = np. linspace( 0 , 10 , 100 ) . reshape( - 1 , 1 )
y = np. sin( x) . ravel( ) + 0.3 * x. ravel( ) + np. random. normal( 0 , 0.3 , 100 )
model = make_pipeline(
SplineTransformer( n_knots= 5 , degree= 3 ) ,
LinearRegression( )
)
model. fit( x, y)
y_pred = model. predict( x)
print ( "R^2 score:" , model. score( x, y) ) 技术支持
scikit-learn R2 分数
SplineTransformer 使用 5 个结与三次多项式创建样条基,然后 LinearRegression 为每个基函数求系数。您可以在这里替换为任意 sklearn 回归器——ridge、lasso,只要是在变换后的特征上拟合线性模型即可。
这种方法契合 sklearn 的工作流,但得不到诸如标准误或 p 值等统计输出。若需要这些,请使用 patsy 或 statsmodels。
使用 patsy
patsy 是构建设计矩阵的基于公式的接口,是 Python 最接近 R 模型公式的工具,也是与 statsmodels 搭配构造样条特征的标准方式。
import numpy as np
import pandas as pd
from patsy import dmatrix
import statsmodels. api as sm
np. random. seed( 42 )
x = np. linspace( 0 , 10 , 100 )
y = np. sin( x) + 0.3 * x + np. random. normal( 0 , 0.3 , 100 )
df = pd. DataFrame( { "x" : x, "y" : y} )
spline_basis = dmatrix( "bs(x, df=6, degree=3)" , data= df, return_type= "dataframe" )
model = sm. OLS( df[ "y" ] , spline_basis) . fit( )
print ( model. summary( ) ) 技术支持
patsy 模型摘要
bs() 函数在公式中指示 patsy 构建具有 6 个自由度、三次(degree 3)的 B-样条基。patsy 返回设计矩阵,直接输入 sm.OLS()。df 参数控制样条基函数的数量——数值越大越灵活,类似于增加更多结。
若需要自然样条,只需将 bs() 改为 ns():
spline_basis = dmatrix( "ns(x, df=6)" , data= df, return_type= "dataframe" ) 技术支持
使用带公式的 statsmodels
statsmodels 也有与 patsy 集成的公式 API。当您想用一行代码完成样条回归并获得完整统计输出时,这是最简洁的方式。
import statsmodels. formula. api as smf
model = smf. ols( "y ~ bs(x, df=7, degree=3)" , data= df) . fit( )
print ( model. summary( ) ) 技术支持
statsmodels 模型摘要
summary() 输出包括每个样条基函数的系数、标准误、p 值及常见拟合统计量。系数本身并不直接可解释,因为每个系数对应一个基函数,而非真实世界量。应通过在自变量范围内绘制预测来解读拟合结果。
对于大多数统计工作流而言,statsmodels 的公式 API 最为方便。当样条是大型 ML 流水线的一部分时,使用 scikit-learn。
R 中的样条回归
在主流语言中,R 对样条的内置支持最佳。splines 包随 R 基础发行版提供,其两个主要函数——bs() 与 ns()——可直接用于任意回归公式中。
bs() 函数创建 B-样条基;ns() 函数创建自然三次样条基。两者都会生成样条特征矩阵,R 的公式系统会自动将其插入模型。
使用 bs() 构建 B-样条
set.seed( 42 )
x <- seq( 0 , 10 , length.out = 100 )
y <- sin( x) + 0.3 * x + rnorm( 100 , sd = 0.3 )
df <- data.frame( x = x, y = y)
library( splines)
model <- lm( y ~ bs( x, df = 6 , degree = 3 ) , data = df)
summary( model) 技术支持
R 中 bs() 输出
公式 y ~ bs(x, df = 6, degree = 3) 指示 R 用三次、6 个自由度的 B-样条基替换 x 。其余由 R 处理——构建基矩阵、拟合线性模型,并生成包含常规诊断的标准 lm 对象。
如需完全控制,可直接传入结的位置:
model <- lm( y ~ bs( x, knots = c( 2 , 5 , 8 ) , degree = 3 ) , data = df) 技术支持
这会把结放在 x = 2、x = 5 与 x = 8 处,而不是让 R 自动选择。
使用 ns() 构建自然样条
若需自然三次样条(即边界外线性行为),使用 ns():
model_natural <- lm( y ~ ns( x, df = 6 ) , data = df)
summary( model_natural) 技术支持
R 中 ns() 输出
语法相同,但边界行为不同。若您关心边界附近的预测或解释,自然样条通常更稳妥。
解释输出
在 summary() 中的系数对应的是样条基函数,而非可直接解释的量。要看模型到底学到了什么,应在一组 x 网格上做预测并绘图:
x_grid <- data.frame( x = seq( 0 , 10 , length.out = 200 ) )
preds <- predict( model, newdata = x_grid)
plot( df$ x, df$ y)
lines( x_grid$ x, preds, col = "green" , lwd = 2 ) 技术支持
R 中的输出解读
这是 R 中的常规流程:先拟合样条,再在平滑网格上预测,并将曲线叠加到数据上。R 也允许在同一公式中将样条项与其他自变量一并使用:
model_multi <- lm( y ~ ns( x, df = 6 ) + other_var, data = df) 技术支持
这会在同一个模型中,对 x 建模非线性效应,并对 other_var 建模线性效应。这种灵活性也是样条在基于 R 的统计工作流中广泛使用的原因。
样条回归的优势
以下是与更常见的机器学习模型相比,样条的一些优势:
无需已知形式即可建模非线性关系: 您不必承诺某个特定函数形状。样条让数据来决定曲线形态,因此无需事先知道弯折、平台或方向改变在哪里发生,也能进行建模。
平滑且可解释的拟合: 输出是一条连续曲线,而非黑箱预测。您可以绘制样条,观察响应如何随自变量变化,并向非技术受众进行解释。
比高次多项式更稳定: 每个片段都是低次多项式,因此任何单独部分在极端处都不至于“发疯”。边界行为更可控,尤其是使用自然三次样条时。
易于融入现有回归工作流: 样条可在标准线性回归框架内工作。您可将其与其他自变量、正则化、混合效应以及任何基于 OLS 的工具结合使用。
样条回归的局限
与大多数模型一样,样条也有一些需要了解的权衡:
结的选择最棘手: 选择结的数量与位置需要投入精力。默认值有时有效,但很多情况下需要交叉验证或领域知识来获得良好拟合。不存在放之四海而皆准的规则。
结越多越难解释: 三个结的样条尚易解释;二十个结的样条就难了。您仍可绘制曲线,但要严谨地解释模型在做什么会难得多。
仍可能过拟合: 样条比高次多项式更稳定,但并非免疫。结太多、结位不佳、异常值过多或样本太小,都可能产生在训练数据上表现良好、在新数据上失效的模型。
系数不直接有意义: 拟合得到的系数对应基函数,而非真实世界量。您无法像在线性回归中那样直接读出“x 增加一单位使 y 变化 beta”。需要通过可视化来解读拟合。
样条回归的常见错误
下面介绍新手在样条回归中常见的几个错误:
结用得太多: 初学者常常把结加到在训练数据上“看起来不错”为止。这是典型的过拟合陷阱。如果样条在每个观测之间都左右摆动,说明结太多。请做交叉验证,或从较少的结开始,仅当残差显示出清晰模式时再增加。
结太少并假定数据线性: 相反的错误。如果用一两个结拟合样条而残差仍显示曲率,说明模型欠拟合。样条的片段不够,无法追随真实模式。请在残差偏差明显的区域增加结。
误解边界行为: 常规三次样条在数据边缘可能出现反常行为。如果您要在边界附近预测(或外推),请使用自然三次样条。它们在边界结之外强制线性行为,避免常规三次样条可能产生的摆动。
将样条直接与无约束非线性模型比较: 样条并不试图成为神经网络或随机森林。如果仅就原始预测精度将样条与完全非线性的黑箱模型对比,黑箱模型往往在性能上更好。但这并非重点。样条胜在可解释性和融入传统统计推断的能力。
样条回归与其他非线性建模技术
样条并非建模非线性关系的唯一方法,但当您重视可解释性时,它们很有用。以下与常见替代方案的比较:
多项式回归
多项式回归使用单个全局方程。指定更简单,但在边界处更不稳定。当关系有多个弯折时,样条在灵活性与稳定性上胜过多项式。只有在非常低的次数(2 或 3)下,多项式更易解释;超过这个范围,样条同时变得更可靠且更易解释。
广义加性模型(GAM)
GAM 本质上是规模化的样条。GAM 允许为每个自变量分别拟合样条,并将它们加性组合。您可以把样条回归视为单变量 GAM,而 GAM 则是多个变量上样条之和。
与为每个变量手动拟合样条相比,GAM 更利于同时处理多个非线性自变量。它们还包含平滑惩罚,以选择合适的灵活度,从而减少部分结选择工作。如果您处理多个自变量,且其中有几个需要非线性处理,GAM 通常更优。
决策树
决策树采用完全不同的思路。它们将自变量空间分割为矩形区域,并在每个区域内预测一个常数值。结果是阶梯函数。
在某些方面,树比样条更灵活——它们能建模交互和突变。但拟合函数并不平滑或连续。在数据稀疏区域,它们的泛化也不佳。若您关心平滑性与稳定的外推,样条更合适;若您关心刻画陡峭边界或多变量间的交互,树更有优势。
样条回归的重要性
样条在应用统计中无处不在。它们出现在临床研究、经济分析、环境科学、时间序列建模等各个领域——凡是需要在不使用黑箱模型的前提下建模平滑非线性效应的地方,几乎都有样条的用武之地。
原因在于它们的平衡性——既有足够的灵活性来处理凌乱数据,又有足够的结构来保持可解释与稳定。
样条也是更高级方法的基石。广义加性模型直接建立在样条之上,平滑样条通过内置正则化扩展了这一思想,许多现代非线性回归技术也使用样条基。如果您想理解这些方法,首先要理解样条。
因此,样条之所以重要,一是因为其实用性,二是因为它是许多后续方法的构建基块。它们不是最强大的模型,却往往是最可靠的——而这常常更为关键。
结语
样条回归通过在称为结的点处拼接分段多项式来建模非线性关系。思路如此,其余都是在此基础上的变体。
结与平滑性是您需要掌握的两个核心概念。其余(样条类型、基表示、在 R 与 Python 中的实现)只是围绕这两个概念的不同工作方式。
在自己的数据上尝试几种样条类型。比较三次、自然三次与 B-样条。移动结的位置,看看会发生什么。大胆实验吧,因为拟合具有直观的可视化,能清楚展示每个选择的影响。
如果您想更深入了解样条及许多其他算法背后的数学,请报名我们的 Python 机器学习科学家 学习路径。它包含您在 2026 年求职所需的一切。
用一条直线去拟合会弯曲的数据,注定行不通。
线性回归假定自变量与目标变量之间的关系是直线。不幸的是,大多数现实世界中的关系并非如此。想想收入与支出、时间与增长之间的关系——它们会弯折、变平、再度弯折,并以单一斜率无法表达的方式改变方向。
样条回归的做法是让关系在需要的地方“弯”,同时避免拟合出无约束的狂野曲线。思路是在整个自变量范围内拟合多个平滑的多项式片段,并在特定点将它们衔接起来。
本文将带您理解样条回归的核心概念、结如何控制灵活性、主要样条类型,以及如何在实践中应用。
在学习样条之前,先阅读我们的教程,它将教会您有关 简单线性回归的一切。
什么是样条回归?
样条回归是一种用分段多项式函数来建模非线性关系的回归技术,这些分段在称为“结”的特定点处连接在一起。
因此,样条回归并非用一个方程描述整个关系,而是将自变量范围切分成较小的区间,并在每个区间上分别拟合多项式。这些片段在结处相接,约束条件确保过渡平滑。
最终效果介于两种极端之间。它比线性回归更灵活,后者只能用一条直线贯穿数据;它又比完全无约束的非线性模型(如深度神经网络或核方法)更有结构,后者几乎能拟合任何东西,却很难告诉您它们究竟拟合了什么。
正因如此,样条在应用统计中极为常见。
为什么需要样条回归
真实数据几乎从不沿直线变化。
线性回归常作为建模关系的默认起点,但它有个强假设:自变量对结果的影响在全范围内保持不变。当真实关系弯曲或改变方向时,直线会欠拟合。在极端处误差加大,模型难以跟随模式。
补救办法是使用更灵活的模型。高次多项式回归是一个选项——添加
x^2、x^3、x^4等项,直到曲线能足够弯曲以匹配数据。但当数据边缘点较少时,多项式会在边界处剧烈上扬或下沉,变得不稳定。这种行为称为 Runge 现象,使高次多项式在预测上存在风险。样条回归位于这两种极端之间。
您可以在数据弯曲的地方获得局部灵活性,而不会出现单个高次多项式的整体不稳定。每个片段都是低次多项式(通常为三次),因此任何单独部分都不至于表现异常。并且由于这些片段在结处平滑连接,整体曲线仍像是一个连续函数。
简而言之,样条既有足够的灵活性来追随复杂模式,又有足够的结构在边界处保持稳健。
样条回归如何工作
样条回归通常遵循三个简单步骤。
正是这些约束,让样条看起来像一条整体平滑的曲线:局部弯折,但在整个自变量范围内连续流畅。视觉上,您看不出一个多项式在哪里结束、下一个从哪里开始。
结、 多项式阶数与连续性约束共同定义了样条。改变其中任意一个,都会得到具有不同性质的样条——接下来的部分将具体介绍。
样条回归中的结是什么?
结是自变量轴上一个多项式片段结束、下一个片段开始的点。
可以把它们看作样条的“关节”。若在
x = 5处放置一个结,模型会在小于 5 的取值范围拟合一个多项式,在大于 5 的范围拟合另一个多项式。两者在结处相接,连续性约束确保平滑连接。增加更多结就会得到更多片段,也就意味着曲线能在更多位置弯折。因此,结是控制模型灵活性的主要杠杆。
结的数量决定样条由多少个独立的多项式片段组成;结的位置决定曲线被允许在何处改变形状。只有两个结的样条只能在少数位置弯折;有二十个结的样条几乎可以跟随每一个数据点。
因此,选择合适的结的数量与位置,是样条回归中的关键决策。
结太少
如果结放得太少,样条的片段不足以跟随数据中的真实模式,曲线会过于僵硬。它几乎表现得像一个低次多项式——整体上有些灵活,但无法捕捉局部变化。
设想用一个结的样条去拟合具有三个明显阶段的数据:上升、平台和下降。只有一个结时,样条只有两个片段可用。它可以捕捉上升阶段和另一个阶段,但无法同时覆盖三者。结果与线性回归相同——在样条无法匹配数据形状的地方产生误差。
结太少示例
结太少会导致欠拟合。模型过于平滑,难以有效。
结太多
相反的问题同样糟糕。结放得太多时,样条片段太多,开始拟合数据中的噪声而非真实模式。曲线在每个观测之间来回摆动,追逐随机波动而不是潜在趋势。
在仅有 50 个样本的数据上放置 20 个结的样条,看起来更像“连点成线”的涂鸦而不是模型。它几乎能完美拟合训练数据,但对新数据的预测不可靠。输入的微小变化会引起输出的巨大且不可预测的变化。
结太多示例
结太多会导致过拟合。模型过于灵活,难以泛化。
理想状态是:结的数量足以捕捉数据中的真实弯折,但又不至于让模型开始记忆噪声。下面的内容将介绍如何在实践中作出这样的权衡。
样条的类型
样条有几种不同“口味”,选择主要取决于每个片段使用何种多项式,以及对曲线施加了哪些约束。
线性样条
线性样条是最简单的版本。每个片段都是一条直线,片段在结处连接。
线性样条示例
此处的连续性约束较宽松:结两侧的函数值必须相等,但斜率可以变化。结果看起来像一系列相连的线段,每个结处都有拐角。它足以处理简单的弯折,但曲线有时不够平滑。
当您只关心整体趋势且不在意视觉上的尖锐感时,线性样条很合适。它们也最易解释,因为每个片段都只是具有自身斜率的直线。
三次样条
三次样条是大多数应用中的默认选择。每个片段都是三次多项式(3 次),且其连续性约束比线性样条更严格。
三次样条示例
在每个结处需满足三项条件:函数值相等、一阶导数相等、二阶导数相等。这意味着没有跳变、没有尖角、没有曲率的突变。曲线穿过结点时流畅自然,视觉上看不出过渡发生的位置。
三次是允许平滑曲率变化的最低多项式次数,因此十分流行。更高次数很少带来有用的灵活性,反而使模型更难控制。
自然三次样条
自然三次样条是在数据边界处增加额外约束的变体。
自然三次样条示例
常规三次样条在边缘可能表现异常,尤其是在数据点稀少的地方。最左和最右的片段仍是三次多项式,而三次多项式在外推时可能迅速上扬或下沉。
自然三次样条通过强制边界结处的二阶导数为零来规避这一问题。实践中,这意味着在最外侧结之外,曲线变为线性。外推行为更稳定,因此当您关心靠近数据边界的预测时,自然三次样条更合适。
B-样条
B-样条(basis splines,基样条)是构造样条的另一种方式。它不是直接定义每个多项式片段,而是将样条表示为一组基函数的加权和。
B-样条示例
每个基函数本身就是一个在有限区域内非零的小样条。完整的样条是这些基函数的总和,每个基函数乘以一个由回归估计出的系数。
B-样条数值稳定且易于扩展。Python 与 R 中的大多数现代样条实现都使用 B-样条表示,即便用户接口看起来像常规样条。如果您曾在 R 中调用
bs()或在 scikit-learn 中使用SplineTransformer,那您用的就是 B-样条。样条回归 vs 多项式回归
多项式回归与样条回归都能处理非线性关系,但方法截然不同,差异在于曲线如何构建。
多项式回归
多项式回归在整个自变量范围上拟合单个全局多项式。您选一个次数(2、3、5、10),模型找到一组系数,以最小化全部数据上的误差。曲线由一个方程描述,并在任何位置都遵循这个方程。
听起来很干净,但有问题。单个多项式必须在整个范围内平衡拟合效果,因此某一区域发生的事会影响所有其他区域。若为处理中部的急剧弯折而提高次数,曲线会在边界处开始摆动。这就是前面提到的 Runge 现象——高次多项式在数据边界附近变得不稳定。
另一个问题是多项式回归没有“局部性”概念。在
x = 5处出现的尖峰可能会改变x = 50的拟合形状,因为每个观测都作用于同一个全局方程。样条回归
样条回归把自变量范围分成多个片段,并在每个片段上拟合低次多项式。多项式在结处平滑连接,但彼此相对独立,其形状主要由各自区域内的数据驱动。
这带来局部灵活性。弯折明显的区域得到更弯的多项式;趋势平坦的区域得到近乎平坦的多项式。且由于每个片段都是低次(通常三次),任何单独部分在极端处都不太可能表现怪异。尤其在数据边界附近,您会获得更平滑、更稳定的拟合。
并排比较
多项式与样条回归对比
因此,如果关系只有轻微非线性且您能接受全局拟合,多项式回归可行;若模式更复杂或您关心边界附近的预测,样条更稳妥。
选择结的数量与位置
结的选择是样条回归中最重要的部分。结太少会欠拟合,太多会过拟合;而放置位置也会改变模型能捕捉到哪些模式。
有几种方法,实际中通常会组合使用:
权衡与所有回归问题相同:灵活性与复杂度。更多结意味着更灵活,能跟随更细的模式,也更可能追逐噪声;更少结意味着更稳定、更易解释,但可能错过真实模式。
可以从将 3–5 个结放在分位数位置开始,然后检查残差。如果残差显示出样条未捕捉到的系统性模式,就在该区域增加一个结;如果拟合看起来过于“抖动”,就减掉一个。若需要为选择辩护或模型将投入生产,建议使用交叉验证。
样条回归在机器学习与统计中的应用
凡是需要在不预设具体函数形式的前提下建模平滑的非线性效应,都会看到样条的身影。常见领域包括:
在这些场景中,样条在需要时提供灵活性,同时无需猜测关系的函数形式。这使其既适合探索性建模,也适合作为强调可解释性的生产模型。
Python 中的样条回归
Python 有三种常用方式拟合样条回归:scikit-learn(面向 ML 流水线)、patsy(基于公式的模型指定)与 statsmodels(统计推断)。下面逐一介绍。
使用 scikit-learn
scikit-learn 提供
SplineTransformer,可将数值特征转换为一组 B-样条基函数,然后将这些特征输入任意线性回归模型。scikit-learn R2 分数
SplineTransformer使用 5 个结与三次多项式创建样条基,然后LinearRegression为每个基函数求系数。您可以在这里替换为任意 sklearn 回归器——ridge、lasso,只要是在变换后的特征上拟合线性模型即可。这种方法契合 sklearn 的工作流,但得不到诸如标准误或 p 值等统计输出。若需要这些,请使用 patsy 或 statsmodels。
使用 patsy
patsy 是构建设计矩阵的基于公式的接口,是 Python 最接近 R 模型公式的工具,也是与 statsmodels 搭配构造样条特征的标准方式。
patsy 模型摘要
bs()函数在公式中指示 patsy 构建具有 6 个自由度、三次(degree 3)的 B-样条基。patsy 返回设计矩阵,直接输入sm.OLS()。df参数控制样条基函数的数量——数值越大越灵活,类似于增加更多结。若需要自然样条,只需将
bs()改为ns():使用带公式的 statsmodels
statsmodels 也有与 patsy 集成的公式 API。当您想用一行代码完成样条回归并获得完整统计输出时,这是最简洁的方式。
statsmodels 模型摘要
summary()输出包括每个样条基函数的系数、标准误、p 值及常见拟合统计量。系数本身并不直接可解释,因为每个系数对应一个基函数,而非真实世界量。应通过在自变量范围内绘制预测来解读拟合结果。对于大多数统计工作流而言,statsmodels 的公式 API 最为方便。当样条是大型 ML 流水线的一部分时,使用 scikit-learn。
R 中的样条回归
在主流语言中,R 对样条的内置支持最佳。
splines包随 R 基础发行版提供,其两个主要函数——bs()与ns()——可直接用于任意回归公式中。bs()函数创建 B-样条基;ns()函数创建自然三次样条基。两者都会生成样条特征矩阵,R 的公式系统会自动将其插入模型。使用 bs() 构建 B-样条
R 中 bs() 输出
公式
y ~ bs(x, df = 6, degree = 3)指示 R 用三次、6 个自由度的 B-样条基替换 x。其余由 R 处理——构建基矩阵、拟合线性模型,并生成包含常规诊断的标准lm对象。如需完全控制,可直接传入结的位置:
这会把结放在
x = 2、x = 5与x = 8处,而不是让 R 自动选择。使用 ns() 构建自然样条
若需自然三次样条(即边界外线性行为),使用
ns():R 中 ns() 输出
语法相同,但边界行为不同。若您关心边界附近的预测或解释,自然样条通常更稳妥。
解释输出
在
summary()中的系数对应的是样条基函数,而非可直接解释的量。要看模型到底学到了什么,应在一组x网格上做预测并绘图:R 中的输出解读
这是 R 中的常规流程:先拟合样条,再在平滑网格上预测,并将曲线叠加到数据上。R 也允许在同一公式中将样条项与其他自变量一并使用:
这会在同一个模型中,对
x建模非线性效应,并对other_var建模线性效应。这种灵活性也是样条在基于 R 的统计工作流中广泛使用的原因。样条回归的优势
以下是与更常见的机器学习模型相比,样条的一些优势:
样条回归的局限
与大多数模型一样,样条也有一些需要了解的权衡:
样条回归的常见错误
下面介绍新手在样条回归中常见的几个错误:
样条回归与其他非线性建模技术
样条并非建模非线性关系的唯一方法,但当您重视可解释性时,它们很有用。以下与常见替代方案的比较:
多项式回归
多项式回归使用单个全局方程。指定更简单,但在边界处更不稳定。当关系有多个弯折时,样条在灵活性与稳定性上胜过多项式。只有在非常低的次数(2 或 3)下,多项式更易解释;超过这个范围,样条同时变得更可靠且更易解释。
广义加性模型(GAM)
GAM 本质上是规模化的样条。GAM 允许为每个自变量分别拟合样条,并将它们加性组合。您可以把样条回归视为单变量 GAM,而 GAM 则是多个变量上样条之和。
与为每个变量手动拟合样条相比,GAM 更利于同时处理多个非线性自变量。它们还包含平滑惩罚,以选择合适的灵活度,从而减少部分结选择工作。如果您处理多个自变量,且其中有几个需要非线性处理,GAM 通常更优。
决策树
决策树采用完全不同的思路。它们将自变量空间分割为矩形区域,并在每个区域内预测一个常数值。结果是阶梯函数。
在某些方面,树比样条更灵活——它们能建模交互和突变。但拟合函数并不平滑或连续。在数据稀疏区域,它们的泛化也不佳。若您关心平滑性与稳定的外推,样条更合适;若您关心刻画陡峭边界或多变量间的交互,树更有优势。
样条回归的重要性
样条在应用统计中无处不在。它们出现在临床研究、经济分析、环境科学、时间序列建模等各个领域——凡是需要在不使用黑箱模型的前提下建模平滑非线性效应的地方,几乎都有样条的用武之地。
原因在于它们的平衡性——既有足够的灵活性来处理凌乱数据,又有足够的结构来保持可解释与稳定。
样条也是更高级方法的基石。广义加性模型直接建立在样条之上,平滑样条通过内置正则化扩展了这一思想,许多现代非线性回归技术也使用样条基。如果您想理解这些方法,首先要理解样条。
因此,样条之所以重要,一是因为其实用性,二是因为它是许多后续方法的构建基块。它们不是最强大的模型,却往往是最可靠的——而这常常更为关键。
结语
样条回归通过在称为结的点处拼接分段多项式来建模非线性关系。思路如此,其余都是在此基础上的变体。
结与平滑性是您需要掌握的两个核心概念。其余(样条类型、基表示、在 R 与 Python 中的实现)只是围绕这两个概念的不同工作方式。
在自己的数据上尝试几种样条类型。比较三次、自然三次与 B-样条。移动结的位置,看看会发生什么。大胆实验吧,因为拟合具有直观的可视化,能清楚展示每个选择的影响。
如果您想更深入了解样条及许多其他算法背后的数学,请报名我们的 Python 机器学习科学家学习路径。它包含您在 2026 年求职所需的一切。