# Python实战:用径向基函数(RBF)拟合复杂曲线(附完整代码)
最近在帮一个做工业数据分析的朋友处理一个棘手的问题:他们有一批传感器数据,波动剧烈且毫无规律,用传统的多项式回归拟合,结果要么是欠拟合,要么在数据点之间产生疯狂的振荡。他问我有没有一种方法,既能紧紧“抓住”那些散乱的数据点,又能生成一条足够光滑、看起来合理的曲线。我几乎没怎么犹豫,就推荐了径向基函数插值。这个方法听起来有点学术,但用Python实现起来,其简洁和强大足以让任何处理过“脏数据”的人感到惊喜。它不像神经网络那样需要漫长的训练和复杂的调参,也不像简单插值那样容易产生不自然的波动,对于数据科学入门者或是需要快速解决拟合问题的工程师来说,是一个非常值得放入工具箱的利器。
这篇文章,我们就抛开复杂的理论推导,直接上手Python代码。我会带你一步步构建一个RBF拟合器,理解每个参数的作用,并通过几个生动的例子——从简单的直线到复杂的合成波形——直观感受它的能力。更重要的是,我们会深入讨论如何避免让它“过度表演”(也就是过拟合),以及如何根据你的数据特点调整它的“敏感度”。无论你是想为实验数据寻找一个平滑的表示,还是需要在有限的采样点之间进行高精度插值,相信这篇实战指南都能给你清晰的路径。
## 1. 核心原理:RBF如何“编织”出光滑曲线
在开始写代码之前,我们花几分钟理解一下径向基函数拟合的直观思想。你可以把它想象成一种“影响力叠加”的艺术。
想象一下,你在平面上有一系列已知的数据点,就像夜空中的星星。径向基函数拟合的目标,是用一条光滑的曲线把这些星星串起来。它的做法很巧妙:为每一个数据点(星星)分配一个独特的“光环”。这个光环不是均匀发光的,它的亮度从中心点向四周衰减,就像一个柔和的高斯钟形曲线。在数学上,这个“光环”就是径向基函数,最常用的形式正是高斯函数:
```
φ(r) = exp(- (r²) / (2 * ε²) )
```
这里,`r` 是空间中任意一点到该数据点中心的距离,而 `ε` 是一个关键参数,它控制着光环的“扩散范围”或“宽度”。`ε` 值越大,光环越宽泛,影响力范围越广;值越小,光环越集中,只影响非常邻近的区域。
那么,如何得到最终的拟合曲线呢?答案是将所有数据点的“光环”进行加权求和。每个光环都有一个权重系数 `w_i`。最终的拟合函数 `f(x)` 在任意点 `x` 的值,就是这一点感受到的所有“光环”亮度(即基函数值)乘以其权重后的总和:
`f(x) = Σ [ w_i * φ( ||x - x_i|| ) ]`
这里的核心魔法在于权重 `w_i` 的计算。我们要求这条拟合曲线必须精确地穿过所有已知的数据点。也就是说,对于第 `j` 个数据点 `(x_j, y_j)`,代入上面的公式后,计算出的 `f(x_j)` 必须等于真实的 `y_j`。把这个条件应用到所有 `n` 个数据点上,就会得到一个由 `n` 个方程构成的线性方程组。
我们可以把这个方程组写成简洁的矩阵形式:
```
Φ * w = y
```
其中:
* `Φ` 是一个 `n x n` 的矩阵,它的第 `i` 行第 `j` 列元素 `Φ_ij = φ( ||x_i - x_j|| )`,代表了第 `j` 个点的光环在第 `i` 个点位置上的亮度。由于距离是对称的,这个矩阵通常是对称的。
* `w` 是一个 `n x 1` 的列向量,包含了我们需要求解的所有权重 `[w_1, w_2, ..., w_n]^T`。
* `y` 是一个 `n x 1` 的列向量,是所有数据点的已知目标值 `[y_1, y_2, ..., y_n]^T`。
这样一来,求解权重 `w` 就变成了一个线性代数问题:`w = Φ^(-1) * y`。只要矩阵 `Φ` 是可逆的(对于高斯核等正定核,在数据点互异时通常可逆),我们就能直接解出权重。这就是RBF拟合在原理上既直接又强大的地方——它通过求解一个线性系统,就能构造出一个可以精确穿过所有数据点的、无限次可微的光滑函数。
> 注意:这里我们讨论的是“插值”模式,即曲线严格经过每个数据点。后面我们会看到,当数据有噪声时,我们可能需要引入正则化,允许曲线不完全穿过数据点,以获得更平滑的结果。
## 2. 从零搭建:手写一个RBF拟合器
理解了原理,我们立刻用Python来实现它。我们将不使用`scipy`或`sklearn`的现成模块,而是从零开始构建,这样你能对每一个步骤都了然于胸。
首先,导入必要的库:
```python
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import solve
```
我们选择`scipy.linalg.solve`来求解线性方程组,这比直接计算矩阵逆在数值上更稳定。
### 2.1 定义径向基函数(核函数)
虽然高斯核最常用,但RBF家族还有其他成员。让我们实现几个常见的,方便后续对比。
```python
def rbf_kernel(x, c, epsilon, kernel_type='gaussian'):
"""
计算径向基函数值。
参数:
x : 标量或数组,输入点。
c : 标量,基函数的中心点。
epsilon : 标量,形状参数(长度尺度),控制函数的宽度。
kernel_type : 字符串,核函数类型。可选 'gaussian', 'multiquadric', 'inverse_quadric', 'thin_plate'。
返回:
标量或数组,核函数在x处的值。
"""
r = np.abs(x - c) / epsilon # 归一化距离
if kernel_type == 'gaussian':
return np.exp(-(r ** 2))
elif kernel_type == 'multiquadric':
return np.sqrt(1 + (r ** 2))
elif kernel_type == 'inverse_quadric':
return 1.0 / (1 + (r ** 2))
elif kernel_type == 'thin_plate':
# 薄板样条核,当r=0时需特殊处理
r = np.where(r == 0, 1e-12, r)
return (r ** 2) * np.log(r)
else:
raise ValueError(f"不支持的核函数类型: {kernel_type}")
```
> 提示:`epsilon` 参数至关重要。你可以将其理解为基函数的“影响半径”。较小的 `epsilon` 使基函数更“尖”,拟合的曲线会更曲折以穿过每一个点;较大的 `epsilon` 使基函数更“平缓”,拟合的曲线整体更光滑。它通常需要根据数据点的间距来调整。
### 2.2 构建并求解权重矩阵
接下来,我们实现核心的拟合函数,它接收数据点,计算矩阵 `Φ`,并求解权重 `w`。
```python
def rbf_fit(x_train, y_train, epsilon=1.0, kernel_type='gaussian'):
"""
使用RBF拟合给定数据,并返回权重。
参数:
x_train : 一维数组,形状 (n_samples,),训练数据的特征。
y_train : 一维数组,形状 (n_samples,),训练数据的目标值。
epsilon : 标量,核函数的形状参数。
kernel_type : 字符串,核函数类型。
返回:
w : 一维数组,形状 (n_samples,),拟合权重。
centers : 一维数组,形状 (n_samples,),基函数中心(即x_train)。
epsilon : 标量,使用的形状参数。
kernel_type : 字符串,使用的核函数类型。
"""
n = len(x_train)
# 确保输入是一维数组
x_train = np.asarray(x_train).ravel()
y_train = np.asarray(y_train).ravel()
# 基函数的中心就是训练点本身
centers = x_train.copy()
# 构建插值矩阵 Phi (n x n)
Phi = np.zeros((n, n))
for i in range(n):
for j in range(n):
# 计算第j个中心对第i个训练点的影响
Phi[i, j] = rbf_kernel(x_train[i], centers[j], epsilon, kernel_type)
# 求解线性方程组 Phi * w = y_train
# 使用 scipy.linalg.solve 比直接求逆更稳定
w = solve(Phi, y_train)
return w, centers, epsilon, kernel_type
```
### 2.3 实现预测函数
有了权重 `w`、中心点 `centers` 和核函数参数,我们就可以对新的输入 `x` 进行预测了。
```python
def rbf_predict(x_new, w, centers, epsilon, kernel_type):
"""
使用拟合好的RBF模型进行预测。
参数:
x_new : 一维数组,形状 (m,),需要预测的点。
w : 一维数组,形状 (n_samples,),拟合权重。
centers : 一维数组,形状 (n_samples,),基函数中心。
epsilon : 标量,形状参数。
kernel_type : 字符串,核函数类型。
返回:
y_pred : 一维数组,形状 (m,),在x_new处的预测值。
"""
x_new = np.asarray(x_new).ravel()
m = len(x_new)
n = len(centers)
y_pred = np.zeros(m)
for i in range(m):
# 对每一个新的x点,计算所有基函数加权和
for j in range(n):
y_pred[i] += w[j] * rbf_kernel(x_new[i], centers[j], epsilon, kernel_type)
return y_pred
```
为了方便使用,我们可以将上述功能封装成一个简单的类:
```python
class SimpleRBF:
"""一个简易的径向基函数插值器。"""
def __init__(self, epsilon=1.0, kernel='gaussian'):
self.epsilon = epsilon
self.kernel = kernel
self.w = None
self.centers = None
def fit(self, x, y):
"""拟合数据。"""
self.w, self.centers, self.epsilon, self.kernel = rbf_fit(
x, y, self.epsilon, self.kernel
)
return self
def predict(self, x):
"""预测新数据。"""
if self.w is None:
raise ValueError("模型尚未拟合,请先调用 fit 方法。")
return rbf_predict(x, self.w, self.centers, self.epsilon, self.kernel)
```
现在,我们的手写RBF拟合器就完成了。让我们用一个简单的例子测试一下。
## 3. 实战演练:驯服复杂波形
理论说得再多,不如代码跑一遍。我们设计一个包含多种频率和趋势的复杂目标函数,然后用稀疏的采样点去拟合它,看看RBF的表现。
### 3.1 创建复杂目标函数与采样数据
我们定义一个“魔鬼曲线”,它结合了多项式、三角函数和噪声,模拟真实世界中复杂的信号。
```python
def target_function(x):
"""一个复杂的目标函数,用于演示。"""
return (
0.5 * x * np.sin(2 * x) + # 振幅增长的振荡
0.1 * (x - 2)**2 + # 二次项趋势
2 * np.cos(0.5 * x) + # 低频振荡
np.where(x > 3, 1.5, 0) # 在x>3处引入一个阶跃
)
# 生成密集的点用于绘制真实函数曲线
x_dense = np.linspace(-5, 10, 1000)
y_true = target_function(x_dense)
# 生成稀疏的、带噪声的采样点(模拟实际测量数据)
np.random.seed(42) # 确保结果可复现
n_samples = 15
x_sample = np.random.uniform(-4, 9, n_samples) # 在区间内随机采样
y_sample = target_function(x_sample) + np.random.normal(0, 0.1, n_samples) # 加入高斯噪声
# 可视化原始数据
plt.figure(figsize=(10, 6))
plt.plot(x_dense, y_true, 'b-', linewidth=2, alpha=0.7, label='真实函数')
plt.scatter(x_sample, y_sample, c='red', s=50, zorder=5, label='带噪声采样点')
plt.xlabel('x')
plt.ylabel('y')
plt.title('复杂目标函数与稀疏采样点')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
```
运行这段代码,你会看到一条蓝色的复杂曲线和其上随机散布的红色采样点。我们的任务就是仅用这些红点,去尽可能还原那条蓝线。
### 3.2 首次拟合与参数 `epsilon` 的探索
现在,使用我们刚写的 `SimpleRBF` 类进行拟合。我们先尝试一个默认的 `epsilon` 值。
```python
# 使用默认参数拟合
model_default = SimpleRBF(epsilon=1.0, kernel='gaussian')
model_default.fit(x_sample, y_sample)
y_pred_default = model_default.predict(x_dense)
# 可视化拟合结果
plt.figure(figsize=(12, 8))
plt.plot(x_dense, y_true, 'b-', linewidth=2, alpha=0.5, label='真实函数')
plt.scatter(x_sample, y_sample, c='red', s=70, zorder=5, label='采样点')
plt.plot(x_dense, y_pred_default, 'g--', linewidth=2.5, label=f'RBF拟合 (epsilon=1.0)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('RBF拟合效果 (默认参数)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
```
观察结果,绿色的虚线是我们的拟合曲线。你可能会发现两个问题:
1. **过拟合迹象**:曲线在采样点附近可能有不自然的剧烈波动,尤其是在采样点稀疏的区域。
2. **欠拟合可能**:如果 `epsilon` 太大,曲线可能过于平滑,无法捕捉数据的快速变化。
这引出了RBF拟合中最关键的调参环节:**选择合适的影响半径 `epsilon`**。让我们系统性地比较一下不同 `epsilon` 值的效果。
```python
# 测试不同的 epsilon 值
epsilon_values = [0.1, 0.5, 2.0, 5.0]
plt.figure(figsize=(14, 10))
for idx, eps in enumerate(epsilon_values, 1):
model = SimpleRBF(epsilon=eps, kernel='gaussian')
model.fit(x_sample, y_sample)
y_pred = model.predict(x_dense)
plt.subplot(2, 2, idx)
plt.plot(x_dense, y_true, 'b-', linewidth=1.5, alpha=0.4, label='真实函数')
plt.scatter(x_sample, y_sample, c='red', s=40, zorder=5, alpha=0.7)
plt.plot(x_dense, y_pred, 'orange', linewidth=2, label=f'eps={eps}')
plt.title(f'epsilon = {eps}')
plt.legend(loc='upper left', fontsize='small')
plt.grid(True, alpha=0.3)
plt.suptitle('不同 epsilon 参数对RBF拟合效果的影响', fontsize=16)
plt.tight_layout()
plt.show()
```
通过这个对比图,你可以清晰地看到:
* `epsilon=0.1`:基函数非常“窄”,拟合曲线疯狂地穿过每一个数据点,在点与点之间剧烈振荡,这是典型的**过拟合**。它对数据中的噪声也极度敏感。
* `epsilon=0.5`:情况有所改善,曲线相对更光滑,但仍有一些不必要的波动。
* `epsilon=2.0`:在这个例子中,这可能是一个较好的折中选择。曲线既保持了整体趋势,又足够光滑,对噪声有一定的鲁棒性。
* `epsilon=5.0`:基函数太“宽”,曲线过于平滑,失去了原函数中的一些细节特征(如`x>3`处的阶跃),导致**欠拟合**。
### 3.3 核函数类型对比
除了 `epsilon`,核函数类型也影响着拟合曲线的性质。我们快速对比一下四种核函数在相同 `epsilon` 下的表现。
```python
# 测试不同的核函数,固定一个适中的 epsilon
kernel_types = ['gaussian', 'multiquadric', 'inverse_quadric', 'thin_plate']
eps = 1.5
plt.figure(figsize=(14, 10))
for idx, kernel in enumerate(kernel_types, 1):
try:
model = SimpleRBF(epsilon=eps, kernel=kernel)
model.fit(x_sample, y_sample)
y_pred = model.predict(x_dense)
plt.subplot(2, 2, idx)
plt.plot(x_dense, y_true, 'b-', linewidth=1.5, alpha=0.4, label='真实函数')
plt.scatter(x_sample, y_sample, c='red', s=40, zorder=5, alpha=0.7)
plt.plot(x_dense, y_pred, 'purple', linewidth=2, label=f'{kernel}')
plt.title(f'核函数: {kernel} (epsilon={eps})')
plt.legend(loc='upper left', fontsize='small')
plt.grid(True, alpha=0.3)
except Exception as e:
plt.subplot(2, 2, idx)
plt.text(0.5, 0.5, f'Error:\n{str(e)}', ha='center', va='center')
plt.title(f'核函数: {kernel} 出错')
plt.suptitle('不同径向基核函数拟合效果对比', fontsize=16)
plt.tight_layout()
plt.show()
```
你会观察到:
* **高斯核 (Gaussian)**:产生非常光滑的曲线,是最常用的选择。
* **多重二次曲面核 (Multiquadric)**:拟合的曲线相对不那么“软”,有时在数据点外推时增长更快。
* **逆二次曲面核 (Inverse Quadric)**:性质与高斯核类似,也是衰减很快的光滑函数。
* **薄板样条核 (Thin Plate)**:这是一种“条件正定”核,通常能产生看起来更“自然”的插值曲面,尤其在处理散乱数据时。注意它在 `r=0` 处的奇异性,我们的代码做了简单处理。
对于大多数应用,从高斯核开始尝试是一个稳妥的选择。
## 4. 进阶技巧与避坑指南
掌握了基本用法后,我们来看看如何让RBF拟合更稳健、更实用。
### 4.1 处理噪声:引入正则化
当数据含有显著噪声时,强迫拟合曲线穿过每一个点(精确插值)并不是好主意,这会放大噪声。此时,我们需要引入**正则化**,允许拟合曲线不完全通过数据点,以换取整体的平滑性。这通过修改线性方程组来实现:
`(Φ + λ * I) * w = y`
其中 `λ` 是正则化参数,`I` 是单位矩阵。`λ` 越大,平滑性越强,对数据的拟合偏差也越大。
让我们修改 `rbf_fit` 函数,加入正则化选项:
```python
def rbf_fit_regularized(x_train, y_train, epsilon=1.0, kernel_type='gaussian', reg_param=0.0):
"""
使用带正则化的RBF拟合给定数据。
"""
n = len(x_train)
x_train = np.asarray(x_train).ravel()
y_train = np.asarray(y_train).ravel()
centers = x_train.copy()
Phi = np.zeros((n, n))
for i in range(n):
for j in range(n):
Phi[i, j] = rbf_kernel(x_train[i], centers[j], epsilon, kernel_type)
# 添加正则化项:在Phi的对角线上加上 reg_param
Phi_reg = Phi + reg_param * np.eye(n)
w = solve(Phi_reg, y_train)
return w, centers, epsilon, kernel_type, reg_param
```
然后,我们对比一下有无正则化对含噪声数据拟合的影响。
```python
# 生成更嘈杂的数据
np.random.seed(123)
x_noisy = np.linspace(-5, 5, 25)
y_noisy = np.sin(x_noisy) + np.random.normal(0, 0.3, len(x_noisy))
x_fine = np.linspace(-5.5, 5.5, 500)
y_true_fine = np.sin(x_fine)
# 拟合:无正则化 (精确插值)
w_noreg, centers_noreg, eps, kern, _ = rbf_fit_regularized(x_noisy, y_noisy, epsilon=0.8, reg_param=0.0)
y_pred_noreg = rbf_predict(x_fine, w_noreg, centers_noreg, eps, kern)
# 拟合:带正则化 (平滑)
w_reg, centers_reg, eps, kern, lam = rbf_fit_regularized(x_noisy, y_noisy, epsilon=2.0, reg_param=0.1)
y_pred_reg = rbf_predict(x_fine, w_reg, centers_reg, eps, kern)
# 可视化对比
plt.figure(figsize=(13, 5))
plt.subplot(1, 2, 1)
plt.plot(x_fine, y_true_fine, 'b-', alpha=0.4, label='真实信号 (sin(x))')
plt.scatter(x_noisy, y_noisy, c='red', s=30, alpha=0.7, label='含噪声数据')
plt.plot(x_fine, y_pred_noreg, 'g--', linewidth=2, label='无正则化 (插值)')
plt.title('无正则化:过拟合噪声')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.plot(x_fine, y_true_fine, 'b-', alpha=0.4, label='真实信号 (sin(x))')
plt.scatter(x_noisy, y_noisy, c='red', s=30, alpha=0.7, label='含噪声数据')
plt.plot(x_fine, y_pred_reg, 'orange', linewidth=2, label=f'带正则化 (λ={lam})')
plt.title('带正则化:平滑拟合')
plt.legend()
plt.grid(True, alpha=0.3)
plt.suptitle('正则化在含噪声数据拟合中的作用', fontsize=14)
plt.tight_layout()
plt.show()
```
左侧的无正则化拟合,曲线穿过了每一个噪声点,导致在数据点之间产生了毫无意义的振荡。右侧的正则化拟合,虽然不完全穿过每个点,但得到了一条更接近原始正弦波的光滑曲线,这才是我们想要的信号趋势。
### 4.2 参数选择策略与常见陷阱
在实际项目中,如何选择 `epsilon` 和 `reg_param` 呢?这里有一些经验法则和技巧:
1. **`epsilon` 的初始估计**:一个常用的启发式方法是取数据点之间平均距离的倍数。例如:
```python
from scipy.spatial import distance
pairwise_dist = distance.pdist(x_sample.reshape(-1, 1))
mean_dist = np.mean(pairwise_dist)
initial_epsilon = 1.0 * mean_dist # 从1倍平均距离开始尝试
```
2. **使用交叉验证**:对于有标签数据,最可靠的方法是使用交叉验证。将数据分成训练集和验证集,在训练集上拟合,在验证集上评估误差(如均方误差MSE),选择使验证误差最小的参数组合。
3. **网格搜索**:对于 `epsilon` 和 `reg_param`,可以定义一个参数网格进行搜索。
```python
# 简单的网格搜索示例(需结合交叉验证)
epsilon_grid = np.logspace(-1, 1, 10) # 从0.1到10,对数间隔
lambda_grid = np.logspace(-3, 0, 8) # 从0.001到1
best_score = np.inf
best_params = {}
# ... 此处实现交叉验证循环,计算分数 ...
```
4. **常见陷阱**:
* **数据点太密集或 `epsilon` 太小**:会导致插值矩阵 `Φ` 接近奇异(病态),求解权重时数值不稳定,结果可能溢出或产生巨大误差。解决方法:增加正则化参数 `reg_param`。
* **外推不可靠**:RBF拟合在数据范围之外的预测(外推)行为通常不可控,可能会急剧上升或下降。**永远不要过分依赖RBF在训练数据区域之外的预测结果**。
* **计算复杂度**:求解 `n x n` 线性方程组的复杂度是 O(n³),当数据点很多(例如 n > 几千)时,计算会非常缓慢且耗内存。对于大规模数据,需要考虑使用**贪婪算法选取少量中心点**,或采用**快速多极子方法 (FMM)** 等加速技术,但这通常超出了基础应用的范畴。
### 4.3 完整项目示例:拟合传感器时序数据
假设我们有一段来自温度传感器的、采样不均匀且带有噪声的时序数据,目标是重建一条光滑的温度变化曲线。
```python
# 模拟传感器数据
np.random.seed(2024)
time_raw = np.sort(np.random.uniform(0, 24, 40)) # 40个不均匀的时间点
# 模拟温度:日间周期 + 随机波动 + 噪声
temp_raw = 15 + 8 * np.sin(2 * np.pi * time_raw / 24 + 0.5) + \
np.random.normal(0, 1.5, len(time_raw)) + \
0.05 * (time_raw - 12)**2
# 准备密集时间点用于平滑预测
time_dense = np.linspace(0, 24, 500)
# 使用RBF拟合(选择高斯核,并尝试寻找合适参数)
# 通过简单尝试,我们选择 epsilon=2.5, reg_param=0.01
model_sensor = SimpleRBF(epsilon=2.5, kernel='gaussian')
# 注意:我们的SimpleRBF类需要稍作修改以支持正则化,这里为了演示,假设已修改。
# 我们使用一个假定的“fit_regularized”方法。
w_sensor, centers_sensor, eps_sensor, kern_sensor, lam_sensor = rbf_fit_regularized(
time_raw, temp_raw, epsilon=2.5, kernel_type='gaussian', reg_param=0.01
)
temp_smooth = rbf_predict(time_dense, w_sensor, centers_sensor, eps_sensor, kern_sensor)
# 可视化
plt.figure(figsize=(12, 6))
plt.scatter(time_raw, temp_raw, c='darkorange', s=40, alpha=0.7, edgecolors='k', linewidth=0.5, label='原始传感器数据')
plt.plot(time_dense, temp_smooth, 'b-', linewidth=2.5, label='RBF平滑拟合曲线')
plt.fill_between(time_dense, temp_smooth - 1.5, temp_smooth + 1.5, color='blue', alpha=0.15, label='估计波动范围 (±1.5°C)')
plt.xlabel('时间 (小时)')
plt.ylabel('温度 (°C)')
plt.title('基于RBF的传感器数据平滑与趋势提取')
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)
plt.xlim(0, 24)
plt.show()
# 输出一些拟合信息
print(f"拟合参数:epsilon = {eps_sensor:.2f}, 正则化参数 lambda = {lam_sensor:.3f}")
print(f"使用了 {len(centers_sensor)} 个径向基函数中心。")
```
在这段代码中,我们模拟了非均匀采样的传感器数据,并利用RBF拟合出了一条光滑的趋势曲线。蓝色的拟合曲线滤除了大部分随机噪声,清晰地显示了温度的日变化周期以及可能的缓慢升温趋势(通过二次项模拟)。阴影区域可以直观地表示拟合结果的不确定性或数据的自然波动范围。
通过这个完整的实战流程,从原理推导、代码实现、参数调优到实际应用,你应该已经掌握了使用径向基函数在Python中拟合复杂曲线的核心技能。记住,RBF是一个强大而灵活的工具,但像所有工具一样,理解其局限性和正确的调参方法,才能让它在你手中发挥最大效用。下次当你面对那些用传统方法难以驾驭的散乱数据时,不妨试试RBF,它可能会给你带来意想不到的平滑与精确。