5

我有一组 x、y 点,我想找到最适合的线,使该线低于使用 SciPy 的所有点。我正在尝试为此使用 minimumsq,但我不确定如何将线调整为低于所有点而不是最佳拟合线。最佳拟合线的系数可以通过以下方式产生:

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])

如何获得低于所有点的最佳拟合线的系数?

4

1 回答 1

6

一种可能的算法如下:

  1. 移动轴以使所有数据都位于 x 轴的正半部分。

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

  3. 然后,您可以计算拟合误差,它只是 的函数b,并用于scipy.optimize.minimize找到 的最佳值b

  4. 剩下的就是为此计算ab计算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 明智地预测的那样,它通过两个属于凸包的点:

在此处输入图像描述

于 2013-01-24T00:35:52.777 回答