三维多项式拟合

时间:2015-07-24 09:33:01

标签: python scipy curve-fitting

我有一组数据,我想使用以下3D多项式来拟合:

y = c1 + c2 * u + c3 * v + c4 * u² + c5 * (u*v) + c6 * v² + c7 * u³ + c8 *  (v * u²) + c9 * (u * v²) + c10 * v³

我尝试使用curve_fit,但它只适用于给定的数据集。给定数据之间的任何点都会给出错误的ZZ。 有更好的解决方案吗?

任何帮助将不胜感激!

代码:

import numpy as np
#import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import scipy

def fnc(u, v, params):
    c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 = params
    return c1 + c2 * u + c3 * v + c4 * u**2 + c5 * (u*v) + c6 * v**2 + c7 * u**3 + c8 * ( v * u**2 ) + c9 * (u * v**2) + c10 * v**3

def fn(params, f, u, v):
    c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 = params
    return np.ravel(c1 + c2*u + c3*v + c4*u**2+c5*(u*v)+c6*v**2+c7*u**3+c8*(v*u**2)+c9*(u*v**2)+c10*v**3-f)

x = np.transpose(np.array([-25.0,-20.0,-15.0,-10.0,-5.0,0.0,5.0,10.0]))
y = np.transpose(np.array([40.0,50.0,60.0]))
XX,YY = np.meshgrid(x,y)
XX = np.transpose(XX)
YY = np.transpose(YY)

ZZ = np.transpose(np.array([[3878.00,4636.00,5489.00,6483.00,7616.00,8844.00,10245.00,11865.00],[3712.00,4298.00,5123.00,6004.00,7030.00,8161.00,9503.00,11004.00],[3548.00,4064.00,4707.00,5529.00,6434.00,7506.00,8716.00,10070.00]]))

p0 = [0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]

print 'XX', XX
print ''
print 'YY', YY
print ''
print 'ZZ', ZZ
print ''

#fitParams, fitCovariances = curve_fit(fn,x0=p0,args=(ZZ,XX,YY),full_output=1)
pfit, pcov, infodict, errmsg, success = scipy.optimize.leastsq(fn,x0=p0,args=(ZZ,XX,YY),full_output=1)

for i in range(len(pfit)):
    print 'c'+str(i+1), '%0.3e' % pfit[i], '%0.3e' % np.absolute(pcov[i][i])**0.5
print ''

#print pcov
#print errmsg
#print success

u = -8.
v = 53.
print 'u', u
print 'v', v
amp = fnc(u, v, pfit)
print 'Value with fitted parameters:', amp

1 个答案:

答案 0 :(得分:0)

让我们用固定的YY=40值绘制样本:

import matplotlib.pyplot as plt

i = 0
plt.plot(XX[i], ZZ[i],'bo')
plt.xlabel('XX[0]')
plt.ylabel('ZZ[0]')
plt.show()

sample at YY=40

具有固定y值的拟合函数:

x = np.arange(start=-25, stop=10, step=0.1)
for y in [40, 50, 53]:
    z = fnc(x, y, pfit)
    plt.plot(x, z, label='y=' + str(y))
plt.xlabel('x')
plt.ylabel('z')
plt.legend()
plt.show()

enter image description here

y=53曲线如此之低看起来很奇怪。

虽然在另一个轴上变得清晰:看一下具有固定x值的拟合函数的图:

y = np.arange(start=40, stop=60, step=0.1)
for x in [-10, -8, -5]:
    z = fnc(x, y, pfit)
    plt.plot(y, z, label='x=' + str(x))
plt.xlabel('y')
plt.ylabel('z')
plt.legend()
plt.show()

enter image description here

在那个轴上,它显然过度拟合。就像在1D中一样,我们拟合了3度的多项式,仅通过3个点。也许你可以增加该轴上的数据点数量?

顺便说一下

x = np.transpose(np.array([-25.0,-20.0,-15.0,-10.0,-5.0,0.0,5.0,10.0]))

是不必要的,请替换为

x = np.array([-25.0,-20.0,-15.0,-10.0,-5.0,0.0,5.0,10.0])