2017-03-03 158 views
2

我想写一些非常基本的Python代码,输出基于输入和输出样本的数字。因此,例如,如果:从曲线拟合Python估计值

x = [1, 2, 3, 4, 5] 
y = [2, 5, 10, 17, 26] 

z = np.interp(7, xp, yp) 
print(z) ##expected 50, actual was 26 

我想有办法找到这些值映射在一起的最佳拟合函数,这样我可以通过它的另一个x值,并得到y值的粗略近似。我尝试阅读scipy.optimize.curve_fit,但据我所知,这不是我应该使用的,因为这使用了预定义的函数,在我的情况下我没有。

注意,我没有限制函数是否应该是线性/周期/二次等,因为我的值会有所不同,但我的假设是,大部分函数应该是线性的。

我也试过numpy.interp但我只是得到y阵列中的最后一个值,无论我输入的是x

编辑:经过与Cleb的答案混乱,然后与肯尼特的原始方法进行比较,这里是我的发现。 enter image description here这里最准确的技术应该是最接近红线的功能。绿线代表kennytm的方法(二次回归是我尝试的最准确的方法),黑线代表Cleb的技术(UnivariateSpline)。看起来,因为UnivariateSpline没有事先知道底层模型,所以在适应函数的值时会稍微好一些,这会使函数的值更精确一些。

+2

您正在寻找的概念是[插入](https://en.wikipedia.org/wiki/Interpolation)。例如,请参阅[scipy插入教程](https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html)以获取['scipy中可用的一些工具的描述.interpolate'包](https://docs.scipy.org/doc/scipy/reference/interpolate.html)。 –

+0

对于一维数据的线性插值,['numpy.interp()'](https://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html)可能就是你需要的一切。 –

+0

@warrenweckesser我不认为这是,我只是试过了。检查我最后的编辑。 – ninesalt

回答

2

另一种选择是使用样条,例如, scipy.interpolate.UnivariateSpline,如果你不关心底层模型(例如线性,立方体等)和过度拟合。

然后,你可以这样做:

from scipy.interpolate import UnivariateSpline 

x = [1, 2, 3, 4, 5] 
y = [2, 5, 10, 17, 26] 
spl = UnivariateSpline(x, y) 

要在x=7得到的估计,你现在可以简单地做:

spl(7) 

返回你所期望的值:

array(49.99999999999993) 

该方法避免了模型的定义。

+0

这不是我不一定关心模型,而只是我不确定。我会尝试你的方法,并且将它与kennytm答案的准确性进行比较。你会说你的方法有多准确? – ninesalt

+0

@ Swailem95:不确定一个人是否可以普遍回答你的问题;它将取决于你处理的数据。我总是将你的实际数据与样条一起绘制,看看它是否“有意义”。让我知道你的比较结果! – Cleb

+1

检查我最后的编辑。 – ninesalt

2

我试过阅读约scipy.optimize.curve_fit,但据我所知,这不是我应该使用的,因为这使用了一个预定义的函数,在我的情况下,我没有。

其实scipy.optimize.curve_fit的功能是你想要的模型。你说你想要的线性回归,那么你用:

def linear(x, a, b): 
    return a*x + b 

fit_params, _ = scipy.optimize.curve_fit(linear, xp, yp) 
print(linear(7, *fit_params)) 
# 36.0 

的二次回归等类似:

def quadratic(x, a, b, c): 
    return a*x*x + b*x + c 

fit_params, _ = scipy.optimize.curve_fit(quadratic, xp, yp) 
print(quadratic(7, *fit_params)) 
# 50.000000000004555 

(的curve_fit第二返回值是输出的协变矩阵,它给出了一个粗略的图片配合有多好)


如果你只是想以适应最小二乘多项式,你可以只use numpy.polyfit

linear_coeff = numpy.polyfit(xp, yp, deg=1) 
print(numpy.polyval(linear_coeff, 7)) 
# 35.999999999999986 

quadratic_coeff = numpy.polyfit(xp, yp, deg=2) 
print(numpy.polyval(quadratic_coeff, 7)) 
# 50.000000000000085 
+1

要将多项式拟合到数据集,另一个选项是'numpy.polyfit()'。 –

+0

如果我不知道数据是线性的还是二次的?就我而言,我有一套从1980年到2014年的年份,每年都映射到不同的价值(功耗),价值并不总是明显的趋势。 – ninesalt

+2

@ Swailem95嗯OP说“大部分功能应该是线性的”。我认为如果你不知道你的数据是什么样的,scipy是不够的。 – kennytm