以数学方式自动计算曲线的“肘部”
Posted
技术标签:
【中文标题】以数学方式自动计算曲线的“肘部”【英文标题】:Compute the 'elbow' for a curve automatically and mathematically 【发布时间】:2011-05-27 04:46:12 【问题描述】:曲线的一个例子如下所示。肘点可能是 x=3 或 4。 如何自动数学计算曲线的肘部?
【问题讨论】:
您可能想在这里问:math.stackexchange.com。但在任何情况下,您都需要提供一些关于曲线是如何产生的以及它可能采取的形状的背景信息。 finding the best trade-off point on a curve的可能重复 这个问题有一个很好的答案。查看我发布的可能重复的链接。 在曲线上找到最佳权衡点的解决方案 (***.com/questions/2018178/…) 是一个很好的建议。但是,此解决方案取决于曲线上的点。我通过寻找具有最大绝对二阶导数的点来接受@ebo 和@Chris Taylor 的建议,对于我在那里的一组离散点 x[i],该点近似于中心差: secondDerivative(i) = x(i+1) + x(i-1) - 2 * x(i); [max,idx] = max(secondDerivative); 【参考方案1】:像这样的函数通常因其形状而被称为L-curves。它们在通过正则化解决不适定问题时出现。
“肘”点是曲线上具有最大绝对二阶导数的点。
【讨论】:
是的,你的想法和 Chris Taylor 一样。谢谢。 另一个问题是为什么'肘'点是曲线上具有最大绝对二阶导数的点?【参考方案2】:您真正想要的是最大curvature 的点。当斜率远小于 1 时,这可以通过二阶导数来近似(正如@ebo 指出的那样),但情况并非总是如此。
【讨论】:
但 m 甚至不是 1。提示:查看轴刻度。【参考方案3】:您可能想要寻找具有最大绝对二阶导数的点,对于您所拥有的一组离散点x[i]
,可以用中心差来近似:
secondDerivative[i] = x[i+1] + x[i-1] - 2 * x[i]
如上所述,您真正想要的是具有最大曲率的点,但二阶导数就可以了,而且这个中心差可以很好地代表二阶导数。
【讨论】:
提供的数据有噪声。你需要比这更小心。例如,您的建议可能会确定 x=12 或 x=19。 感谢您的建议。我将您的想法作为我的解决方案。 嗨,克里斯,你给了我一个很好的答案。你能告诉我这个解决方案是否有参考吗?我想起草一篇论文,所以我需要这个解决方案的参考。 你能解释一下在什么条件下这个近似值是一个不错的估计,在什么条件下会偏离? “你真正想要的是曲率最大的点,但二阶导数就可以了”。关于曲率的观点似乎是正确的,但二阶导数不会总是这样做(也许永远不会这样做):想想像 exp(-x) 这样的函数——它有点像肘部,但它的二阶导数没有任何事件远程类似于人们期望肘部位置的最大值。【参考方案4】:我创建了一个 Python package 来尝试实现 Kneedle algorithm。
重新创建上面的函数并检测最大曲率点:
x = range(1,21)
y = [0.065, 0.039, 0.030, 0.024, 0.023, 0.022, 0.019, 0.0185, 0.0187,
0.016, 0.015, 0.016, 0.0135, 0.0130, 0.0125, 0.0120, 0.0117, 0.0115, 0.0112, 0.013]
kn = KneeLocator(
x,
y,
curve='convex',
direction='decreasing',
interp_method='interp1d',
)
print(kn.knee)
7
import matplotlib.pyplot as plt
plt.xlabel('x')
plt.ylabel('f(x)')
plt.xticks(range(1,21))
plt.plot(x, y, 'bx-')
plt.vlines(kn.knee, plt.ylim()[0], plt.ylim()[1], linestyles='dashed')
更新
Kneed 有一个改进的样条拟合方法来处理局部最小值,使用interp_method='polynomial'
。
kn = KneeLocator(
x,
y,
curve='convex',
direction='decreasing',
interp_method='polynomial',
)
print(kn.knee)
4
还有新剧情:
plt.xlabel('x')
plt.ylabel('f(x)')
plt.xticks(range(1,21))
plt.plot(x, y, 'bx-')
plt.vlines(kn.knee, plt.ylim()[0], plt.ylim()[1], linestyles='dashed')
【讨论】:
以上是关于以数学方式自动计算曲线的“肘部”的主要内容,如果未能解决你的问题,请参考以下文章