【问题标题】:Determine which subset of points follows a polynomial most closely确定哪个点的子集最接近多项式
【发布时间】:2019-08-23 08:54:17
【问题描述】:

我目前正在尝试根据它们的行为对一堆河流进行分类。许多河流的行为与二次多项式非常相似。

但是,有些河流的某些区域与这种模式不同。

我想通过计算所有点与简单多项式的距离来对此进行分类。所以它基本上看起来像这样:

但为了能够做到这一点,我必须只计算那些“正常行为”的点的多项式。否则我的多项式会转移到发散行为的方向,我无法正确计算距离。

这是一些示例数据。

x_test = [-150,-140,-130,-120,-110,-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,0,10,20,30,40,50,60,70,70,80,80,90,90,100,100]
y_test = [0.1,0.11,0.2,0.25,0.25,0.4,0.5,0.4,0.45,0.6,0.5,0.5,0.6,0.6,0.7, 0.7,0.65,0.8,0.85,0.8,1,1,1.2,0.8,1.4,0.75,1.4,0.7,2,0.5]

我可以用 numpy 从它创建一个多项式。

fit = np.polyfit(x_test, y_test, deg=2, full=True)
polynom = np.poly1d(fit[0]) 
simulated_data = polynom(x)

当我绘制它时,我得到以下信息:

ax = plt.gca()
ax.scatter(x_test,y_test)
ax.plot(x, simulated_data)

如您所见,多项式略微向下移动,这是由此处标记为黑色的点引起的:

是否有一种直接的方法可以找到那些不遵循主要趋势的点并将其排除以创建多项式?

【问题讨论】:

  • 需要注意的一点是,这种方法对您选择的参考框架很敏感。如果选择的方式是所有点都“向上”,或者更糟糕的是,河岸倾斜超过 90°,这可能无法得出近似河流的解。不幸的是,我不知道有什么更好的方法,但是一旦我知道了就会回复你。

标签: python classification polynomial-math polynomial-approximations


【解决方案1】:

这看起来更像是一个 AI 问题,而不是一个简单的拟合问题:你个人如何决定什么不合适 - 特别是在你的第二个发散图中,如果你忽略较大的曲线,第一条向上的短曲线看起来是多项式的?

您只需要 3 个点来计算 2 多项式:如何计算 3 个水平间隔良好的点的所有/多个采样的曲线(不一定相信第一个或最后一个点),看看哪个创建的最少离群值 - 比其他 90% 更远的点?

然后,您可以根据剩余的非离群点计算曲线,并检查它是否适合您简单计算的曲线。

编辑:“间隔良好”的意思是每个水平三分之一的点各有一个点 - 使用三个全部卡在一起的点来尝试推断其他点是没有意义的。此外,从您提供的数据来看,您需要一条围绕原点开始向上的曲线,因此您可以过滤一些随机生成的曲线。

编辑:异常值的建议是草率的 - 如果您的数据最后变得更宽,就像小号一样,那么您就有许多合理的拟合,因此只有在明显的马刺处,您才能为异常值提供清晰的标记。如果您计算点与每条随机曲线的距离的直方图,您可以扫描直方图切线中的肩部和不对称性,使其远离钟形曲线,并在该点切出异常值。

从根本上说,我认为数据可能过于复杂,无法进行计算机辅助分析,除非您突破计算机视觉技术:让计算机尽其所能,然后目视检查带注释的图表,看看您是否同意用它。

它也可能有助于绘制垂直轴的对数,因此您正在处理直线。

【讨论】:

  • 这可能有效。您能否澄清“水平间距良好的点”的含义?而且我认为我对异常值检测感到困惑。如果我检查有多少点比其他点的 90% 更远,这不应该总是 10% 吗?
  • @F.Jehn 我的回复对于评论来说太大了,所以我将它添加到答案中!
  • 这基本上适用于我上面提供的示例数据集。但是,我意识到我的示例数据集并未涵盖数据中的所有边缘情况。因此,我现在只是使用适合数据的指数函数这对大多数数据都是我想要的。
【解决方案2】:

一种可行的方法是将点聚集成“主”和“分支”分支,假设有两个分支,一个包含的点比另一个多。之后,每个聚类可用于拟合在河流分支合并点处交叉的多项式。这甚至可以通过使用多项式进行多次迭代,以便通过使用点到多项式的距离作为距离度量而不是聚类算法使用的距离来更好地分类到集群中。

常见的k-means 算法可能不太适合,因为集群不是围绕点聚集,而是围绕曲线聚集。像DBSCAN 这样的算法可能效果更好,因为它们可以处理给定点附近的点密度,这更类似于我们人类在看到上面示例数据集中的模式时所做的事情。

这可能看起来像这样(无效代码):

points = (x_test, y_test)
labels = dbscan(points, k=2, labels=("main", "offshoot"))
polynomial_main = fit_polynomial([points[x.index] for x in labels if x.label = "main"])
polynomial_off = fit_polynomial([points[x.index] for x in labels if x.label = "offshoot"])

# optionally, purely distance based clustering
# might also use different clustering algorithm using distance as measure
points_main = [p for p in points if distance(p, polynomial_main) < distance(p, polynomial_off)]
points_off = [p for p in points if distance(p, polynomial_off) < distance(p, polynomial_main)]
polynomial_main = fit_polynomial(points_main)
polynomial_off = fit_polynomial(points_off)

【讨论】:

    猜你喜欢
    • 2010-12-15
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 2018-08-28
    相关资源
    最近更新 更多