我有多组测量数据,可以使用散点图(图中的红点和黑点)轻松可视化。如果我的测量结果是完美的,那么红点和黑点应该位于一条曲线上。但是它们不是,因此我想以这样的方式“平均”/拟合数据点,以便获得图中的黑线。黑线可以是一条线或一组离散点,与所有测量数据的距离最小。
有人可以帮我开始吗?理想情况下,已经有一个 python 库可以为我处理这个问题,但我对算法描述也很满意。

我有多组测量数据,可以使用散点图(图中的红点和黑点)轻松可视化。如果我的测量结果是完美的,那么红点和黑点应该位于一条曲线上。但是它们不是,因此我想以这样的方式“平均”/拟合数据点,以便获得图中的黑线。黑线可以是一条线或一组离散点,与所有测量数据的距离最小。
有人可以帮我开始吗?理想情况下,已经有一个 python 库可以为我处理这个问题,但我对算法描述也很满意。

根据您的最后评论(您可能有多个测量值并且您不在乎某组测量值是高于还是低于拟合),我认为您正在寻找的是样条拟合。您可以使用 scipy.interpolate B-spline 例程来执行此操作。下面的脚本基于一个函数生成三组数据(您可以考虑为您的系统建模)。对于第一组,它为函数“上方”(红点)添加了一些随机误差,第二组在下方(蓝点),第三组在上方和下方(绿点)。黑线是精确函数的图(没有错误)。
然后使用该scipy.interpolate.splrep函数为该数据生成 B 样条表示。B 样条是多项式函数的分段组合,通常是三次多项式(三次 B 样条),具有一些不错的特性。如果您想了解更多关于它们的信息,我强烈建议您阅读 C. de Boor 和 P. Dierckx 的作品。该scipy.interpolate.splrep函数返回结、系数和顺序的元组。使用该scipy.interpolate.splev函数,您可以在拟合区间内的多个点中评估 B 样条表示。
下面的脚本以洋红色绘制了 B 样条的评估。
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as ip
def f(x):
return np.sin(np.pi*2*x)*np.exp(-2*x)
N=20
err=0.15
data = np.zeros([3*N,2])
#red dots above curve
data[:N,0] = np.sort(np.random.rand(N))
data[:N,1] = f(data[:N,0])+err*np.random.rand(N)
#blue dots below curve
data[N:2*N,0] = np.sort(np.random.rand(N))
data[N:2*N,1] = f(data[N:2*N,0])-err*np.random.rand(N)
#green dots above and below curve
data[2*N:,0] = np.sort(np.random.rand(N))
data[2*N:,1] = f(data[2*N:,0])-2*err*(np.random.rand(N)-0.5)
plt.plot(data[:N,0],data[:N,1],'ro')
plt.plot(data[N:2*N,0],data[N:2*N,1],'bo')
plt.plot(data[2*N:,0],data[2*N:,1],'go')
data = data[data[:,0].argsort()]
x = data[:,0]
y = data[:,1]
y_exact = f(x)
plt.plot(x,y_exact,'k')
w = np.ones([len(x),1])
spl = ip.splrep(x,y,w)
xn = np.linspace(0,1.0,100)
sple = ip.splev(xn,spl)
plt.plot(xn,sple,'m')
plt.show()
要在给定点的红色和黑色标记的情况下重现您的特定图形,您可以使用一块 voronoi 图。换句话说,您的黑线将是最近的红点和最近的黑点之间等距的点集。
但是假设你想做一些不那么做作的事情,你可以使用某种非线性 svm 来代替。例如这里如图所示。
获得连续分段线性近似的一个简单想法是对每对点(红色和相应的黑色)求平均值,并对这些平均值进行分段线性插值。这将产生与您展示的内容接近的东西。(但是,它不使用回归)
这能满足你的需要吗?
对于实现,我认为你可以手动完成,方法很简单。