拟合点下方的直线

5

我有一组x,y点,并希望使用SciPy找到最佳拟合直线,使该直线在所有点下面。我正在尝试使用leastsq实现这个目标,但我不确定如何将直线调整为低于所有点而不是最佳拟合直线。可以通过以下方式生成最佳拟合直线的系数:

def linreg(x, y):

    fit = lambda params, x: params[0] * x - params[1]
    err = lambda p, x, y: (y - fit(p, x))**2 

    # initial slope/intercept
    init_p = np.array((1, 0))

    p, _ = leastsq(err, init_p.copy(), args=(x, y))

    return p

xs = sp.array([1, 2, 3, 4, 5])  
ys = sp.array([10, 20, 30, 40, 50])

print linreg(xs, ys)

输出的结果是最佳拟合直线的系数:

array([  9.99999997e+00,  -1.68071668e-15])

我该如何获取最佳拟合线的系数,使其位于所有点的下方?

这似乎更像是一个数学问题而不是编程问题。请尝试在 http://math.stackexchange.com/ 上提问。 - Neil
我对数学问题相当有把握。这个问题需要最小化“fit”函数,以便最佳拟合线上的所有点都小于y。我不确定如何在SciPy中实现这一点。 - user1728853
1
将每个数据点与最佳拟合线之间的误差最小化必然意味着某些数据点将在该线上方,而另一些则在其下方。您只是想找到最佳拟合线,然后调整y截距,使该线在所有数据点下方通过吗? - Neil
我认为OP想要找到一条最佳拟合线,使其在所有数据点下方。 - turtle
这很困难 - 最佳拟合线肯定会穿过数据集中形成凸包的某个点。 - tzelleke
1个回答

6
一个可能的算法如下:
  1. 将坐标轴移动到x轴正半轴,使得所有数据都在该轴上。

  2. 如果拟合形式为 y = a * x + b,那么对于给定的 b,最佳的 a 拟合值将是连接点 (0, b) 和每个 (x, y) 点的斜率中的最小值。

  3. 然后,您可以计算一个仅与 b 有关的拟合误差,并使用 scipy.optimize.minimize 找到最佳的 b 值。

  4. 剩下的就是计算该 ba 并计算坐标轴原始位置的 b

以下方法通常能够实现大部分操作,除非最小化过程出现一些神秘的错误:
from __future__ import division
import numpy as np
import scipy.optimize
import matplotlib.pyplot as plt

def fit_below(x, y) :
    idx = np.argsort(x)
    x = x[idx]
    y = y[idx]
    x0, y0 = x[0] - 1, y[0]
    x -= x0
    y -= y0

    def error_function_2(b, x, y) :
        a = np.min((y - b) / x)
        return np.sum((y - a * x - b)**2)

    b = scipy.optimize.minimize(error_function_2, [0], args=(x, y)).x[0]

    a = np.min((y - b) / x)

    return a, b - a * x0 + y0

x = np.arange(10).astype(float)
y = x * 2 + 3 + 3 * np.random.rand(len(x))

a, b = fit_below(x, y)

plt.plot(x, y, 'o')
plt.plot(x, a*x + b, '-')
plt.show()

TheodrosZelleke很明智地预测,它经过作为凸包一部分的两个点:

enter image description here


谢谢!这正是我想要做的。 - user1728853

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接