Ransac(随机抽样一致性算法)多项式拟合附近的点
RANSAC(RANdom SAmple Consensus)算法是一种用于拟合数学模型的迭代方法,尤其适用于对数据中有噪声的情况。RANSAC的核心思想是通过迭代从数据集中随机抽取一小部分样本,判断这些样本是否能很好地拟合一个模型,如果可以,那么这个模型有很大的可能是正确的。
在多项式拟合中,我们可以使用RANSAC算法来找到一个通过一组点且距离这些点距离最小的多项式曲线。以下是一个使用RANSAC算法进行多项式拟合的Python实现示例:
import numpy as np
import random
def ransac(data, model_class, min_samples, threshold, max_iterations, stop_at_goal=True, random_seed=None):
"""
RANSAC算法的实现。
:param data: 数据集,是一个(N, 2)的numpy数组,其中每一行都是一个点的坐标。
:param model_class: 模型类,需要实现以下方法:fit(self, data), 拟合模型;evaluate(self, data, model_pars), 评估模型的误差。
:param min_samples: 估计模型所需的最小样本点数。
:param threshold: 数据点被视为局内点的阈值。
:param max_iterations: 最大迭代次数。
:param stop_at_goal: 是否在达到目标迭代次数后就停止迭代。
:param random_seed: 随机数种子,用于可重复的结果。
:return: 最佳模型的参数和内点集合。
"""
best_model = None
best_inliers = None
best_inlier_num = 0
random.seed(random_seed)
data_idx = list(range(data.shape[0]))
for _ in range(max_iterations):
# 随机选择min_samples个样本点
sample_idxs = random.sample(data_idx, min_samples)
sample_points = data[sample_idxs]
# 使用这些样本点来拟合模型
model = model_class()
model_pars = model.fit(sample_points)
# 评估所有数据点与模型的距离
errors = model.evaluate(data, model_pars)
# 将距离小于阈值的点视为内点
inliers_idxs = np.where(errors < threshold)[0]
inliers = data[inliers_idxs]
# 更新最佳模型
if inliers.shape[0] > best_inlier_num:
best_model = model_pars
best_inliers = inliers
best_inlier_num = inliers.shape[0]
# 如果达到目标,并且stop_at_goal为True,则退出迭代
if best_inlier_num >= data.shape[0] * 0.8 and stop_at_goal:
break
return best_model, best_inliers
class PolynomialModel:
"""
多项式模型类。
"""
def fit(self, data):
# 使用np.polyfit来拟合多项式
model_pars = np.polyfit(data[:, 0], data[:, 1], deg=2)
return model_pars
def evaluate(self, data, model_pars):
# 计算数据点到模型的距离
x = data[:, 0]
y = data[:, 1]
predicted_y = np.polyval(model_pars, x)
errors = np.abs(y - predicted_y)
return errors
# 示例数据
np.random.seed(0)
X = np.linspace(-10, 10, 100)
Y = 3 * X ** 2 + 2 * X + 10 + np.random.normal(0, 10, X.shape[0])
data = np.column_stack((X, Y))
# 使用RANSAC拟合多项式模型
model_pars, inliers = ransac(data, PolynomialModel, min_samples=3, threshold=1, max_iterations=1000,random_seed=0)
# 绘制结果
import matplotlib.pyplot as plt
plt.scatter(data[:, 0], data[:, 1], label='Data', color='blue')
plt.scatter(inliers[:, 0], inliers[:, 1], label='Inliers', color='green')
x_line = np.linspace(min(data[:, 0]), max(data[:, 0]), 100)
y_line = np.polyval(model_pars, x_line)
plt.plot(x_line, y_line, label='Fitted model', color='red')
plt.legend()
plt.show()