如何在Python中应用二维曲线拟合?

如何在Python中应用二维曲线拟合?,python,numpy,scipy,curve-fitting,Python,Numpy,Scipy,Curve Fitting,我正在尝试将二维曲线拟合应用于数据集(任意),如下所示: # Data T Z X 1 X 2 X 3 X 4 X 5 100.000 1.000 1.000 1.478 1.304 1.162 0.805 200.000 1.500 2.000 2.314 2.168 2.086 1.801 300.000 2.250 3.000 3.246 3.114 3.058 2.798 400.000 3.375 4.000

我正在尝试将二维曲线拟合应用于数据集(任意),如下所示:

# Data
T   Z   X 1 X 2 X 3 X 4 X 5
100.000 1.000   1.000   1.478   1.304   1.162   0.805
200.000 1.500   2.000   2.314   2.168   2.086   1.801
300.000 2.250   3.000   3.246   3.114   3.058   2.798
400.000 3.375   4.000   4.211   4.087   4.044   3.780
500.000 5.063   5.000   5.189   5.070   5.035   4.780
最终目的是建立Z=f(X,T)形式的相关性

首先,它是使用二次表达式Z=a*x^2+b*x+c沿T的常数值(即沿每行)进行曲线拟合,该曲线拟合给出了每个T的拟合参数,如下所示(作为示例):

现在我想沿着T拟合每个拟合参数,这样我就可以得到a=p*T^2+q*T+r,b=s*T^2+T*T+u等形式的方程。我试着用代码来应用它:

from __future__ import division
from scipy import optimize
import matplotlib.pyplot as plt
import numpy as np

data = open('data.dat', "r")
line = data.readline()
while line.startswith('#'):
    line = data.readline()
data_header = line.split("\t")
data_header[-1] = data_header[-1].strip()


_data_ = np.genfromtxt('data.dat', skiprows=2, delimiter='\t', names = data_header, dtype = None, unpack = True).transpose()
data = np.array(_data_.tolist())
m = data.shape[0]
n = data.shape[1] - 2
print m, n
y_data = np.empty(shape=(m, n))
for i in range(0, m):
    for j in range(0, n):
        y_data[i, j] = (data[i, j+2])
x = _data_['X']
z = _data_['Z']

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

fit_a = np.empty(shape = (m, 1))
fit_b = np.empty(shape = (m, 1))
fit_c = np.empty(shape = (m, 1))
z_fit = np.empty(shape=(m, len(z)))
for j in range(m):
    x_fit = y_data[j, :]
    y_fit = z
    fit_a[j], fit_b[j], fit_c[j] = optimize.curve_fit(quadratic_fit, x_fit, y_fit)[0]
fit_a_fit_a, fit_a_fit_b, fit_a_fit_c, = optimize.curve_fit(quadratic_fit, x, fit_a)[0]
fit_b_fit_a, fit_b_fit_b, fit_b_fit_c, = optimize.curve_fit(quadratic_fit, x, fit_b)[0]
fit_c_fit_a, fit_c_fit_b, fit_c_fit_c, = optimize.curve_fit(quadratic_fit, x, fit_c)[0]
fit_a = fit_a_fit_a * x ** 2 + fit_a_fit_b * x + fit_a_fit_c
fit_b = fit_b_fit_a * x ** 2 + fit_b_fit_b * x + fit_b_fit_c
fit_c = fit_c_fit_a * x ** 2 + fit_c_fit_b * x + fit_c_fit_c
for j in range(m):              
    z_fit[j, :] = (fit_a[j] * x_fit ** 2) + (fit_b[j] * x_fit) + fit_c[j] 
但它给了我以下错误:

ValueError: object too deep for desired array
Traceback (most recent call last):
    fit_a_fit_a, fit_a_fit_b, fit_a_fit_c, = optimize.curve_fit(quadratic_fit, x, fit_a)[0]
  File "scipy/optimize/minpack.py", line 533, in curve_fit
    res = leastsq(func, p0, args=args, full_output=1, **kw)
  File "scipy/optimize/minpack.py", line 378, in leastsq
    gtol, maxfev, epsfcn, factor, diag)
minpack.error: Result from function call is not a proper array of floats.

用Python怎么能做到这一点呢?

我只是玩了一下,我想你的问题在于行

fit_a = np.empty(shape = (m, 1))
fit_b = np.empty(shape = (m, 1))
fit_c = np.empty(shape = (m, 1))
应该是

fit_a = np.empty(shape = (m, ))
fit_b = np.empty(shape = (m, ))
fit_c = np.empty(shape = (m, ))
看起来形状(m,1)应该是正确的,但它与形状(m,)不同,形状(m,)只是一个一维数组。试试看它是否有效


也就是说,我不确定拟合参数是解决这个问题的正确方法,至少据我所知…

我可以借此机会无耻地插入我自己的拟合包吗

我开发它正是为了让像你这样的拟合问题变得更容易。如果没有针对您的问题运行它,我将使用
symfit
解决此问题:

from symfit import parameters, variables, Fit

Z, X, T = variables('Z, X, T')
p, q, r, s, t, u  = parameters('p, q, r, s, t, u')

a = p * T**2 + q * T + r
b = s * T**2 + t * T + u
c = ...
model = {Z: a * X ** 2 + b * X + c}

fit = Fit(model, X=_data_['X'], T=_data_['T'], Z=_data_['Z'])
fit_result = fit.execute()

print(fit_result)

有关更多信息,请查看文档:)。

问题出在optimize.curve\u fit中,可能与递归有关。如果没有该函数/类作为参考,则无法提供太多帮助。是否确实要拟合参数?看起来你真正想要的是对f(x,T)=z进行2D拟合。确切地说,我需要2D拟合。在这种情况下,你仍然可以使用optimize.curve_拟合,但你的“x”数据必须在每个点同时包含x和T。您还需要编辑二次拟合函数,以获得x、y的参数,可能还有它们的组合。看看这是一个很好的参考答案,-我在这里为它制作了一个CPython模块(与原始模块相比有一些优势),这解决了问题,但现在我也觉得我的方法不正确。
from symfit import parameters, variables, Fit

Z, X, T = variables('Z, X, T')
p, q, r, s, t, u  = parameters('p, q, r, s, t, u')

a = p * T**2 + q * T + r
b = s * T**2 + t * T + u
c = ...
model = {Z: a * X ** 2 + b * X + c}

fit = Fit(model, X=_data_['X'], T=_data_['T'], Z=_data_['Z'])
fit_result = fit.execute()

print(fit_result)