python 多项式曲线拟合 - 系数不正确

python polynomial curve fit - coefficients not right

我有以下 x, y 数据(绿色)。我想获得适合我的曲线的多项式函数。在 python 内拟合的曲线看起来不错(蓝色)。 当我使用多项式的系数并自己构建函数时,结果不在蓝色曲线上。对于较小的 X 值,这可能仍然适用,但对于较大的值则完全错误。图中显示了 x=15 和 2.5 的 y(大点)。

数据:

x, y 
0.5883596178    18562.5
0.6656014904    20850
0.7407008741    22700
0.8310800498    24525
0.9479506185    26370
1.0768193651    27922
1.1983161945    29070
1.3837939534    30410
1.6650549531    31800
1.946640319     32740
2.3811442965    33655
2.9126326549    34290
3.6970654824    34800
4.2868951065    34987.5
4.8297935972    35102
5.7876198835    35175
7.3463468386    35050
8.9861037519    34725
10.5490727095   34285
13.2260016159   33450
16.5822270413   32795
20.5352502646   32472
25.7462680049   32475

代码:

data = plb.loadtxt('fig3_1_tiltingRL.dat')

x = data[:,0]
y= data[:,1]
#plt.xscale('log')#plt.set_xscale('log')
coefs = poly.polyfit(x, y, 10)
ffit = poly.polyval(x, coefs)
plt.plot(x, ffit)
plt.plot(x, y, 'o')
print(coefs)
xPoints =15.  
yPt =    (-6.98662492e+03  * xPoints**0  +  6.57987934e+04  * xPoints**1 -\
      4.65689536e+04   * xPoints**2  +  1.85406629e+04  * xPoints**3 -\
      4.49987278e+03   * xPoints**4  +  6.92952944e+02  * xPoints**5 -\
      6.87501257e+01   * xPoints**6  +  4.35851202e+00  * xPoints**7 -\
      1.69771617e-01   * xPoints**8  +  3.68535224e-03  * xPoints**9 -\
      3.39940049e-05   * xPoints**10) 
 print(yPt)
 plt.plot(xPoints, yPt , 'or',label="test" ,markersize=18, color='black')
 plt.show()

在我看来,您使用 poyval 的方式对我来说不合适。尝试用 numpy.linspace 生成 X 轴,然后在其上应用 polyval。 类似于下面的代码。

import numpy as np
import matplotlib.pyplot as plt


data = np.loadtxt('fig3_1_tiltingRL.dat')

x = data[:,0]
y= data[:,1]
#plt.xscale('log')#plt.set_xscale('log')
coefs = np.polyfit(x, y, 10)
ffit = np.polyval(coefs, x)

new_x = np.linspace(0,26)
new_ffit = np.polyval(coefs, new_x)

plt.plot(x, y, 'o', label="Raw")
plt.plot(x, ffit,'x',label="Fit to Raw")
plt.plot(new_x, new_ffit,label="Fit to LinSpace")

# This is ugly. I'd use list comprehension here!
arr = np.linspace(0,26,20)
new_y = []
for xi in arr:
    total = 0
    for i,v in enumerate(coefs[::-1]):
        total += v*xi**i
    new_y.append(total)


plt.plot(arr, new_y, '*', label="Polynomial")

plt.legend(loc=2)
plt.show()

如您所见,有一个驼峰没有出现在您的图中...

您的算法似乎运行良好。你应该代替:

coefs = poly.polyfit(x, y, 10)
ffit = poly.polyval(x, coefs)

这样做:

coefs = poly.polyfit(x, y, 10) # fit data to the polynomial
new_x = np.linspace(0, 30, 50) # new x values to evaluate
ffit = poly.polyval(new_x, coefs) # fitted polynomial evaluated with new data

因此,函数 poly.polyval 将评估 new_x 的所有点,而不是您已知的 x 坐标。

非常感谢您回答我的问题。

silgon 和 RicLeal 提供的解决方案都有效。

最后,因为我有几条曲线,所以我应用了 RicLeal 给出的解决方案。

我的数据记录在 x 轴上。我刚刚修改了 RicLeal 给出的代码,我对结果很满意。

enter image description here

x = data[:,0]
y= data[:,1]
plt.xscale('log')#plt.set_xscale('log')
logx=np.log10(x)
coefs = np.polyfit(logx, y, 10)
ffit = np.polyval(coefs, logx)
print (coefs)


logxmin=math.log10(0.5883596178)
logxmax=math.log10(26.)

new_x = np.logspace(logxmin, logxmax,50)
lognew_x=np.log10(new_x)
new_ffit = np.polyval(coefs, lognew_x)
plt.semilogx(x, y, 'o', label="Raw")
plt.semilogx(x, ffit,'x',label="Fit to Raw")
plt.semilogx(new_x, new_ffit,label="Fit to LogSpace")
print(lognew_x, new_ffit)
# This is ugly. I'd use list comprehension here!
arr = np.logspace(logxmin, logxmax,50)
arrlog= np.log10(arr)
new_y = []
for xi in arrlog:
    total = 0
    for i,v in enumerate(coefs[::-1]):
       #print (v)
       total += v*xi**i
    new_y.append(total) 


    plt.semilogx(arr, new_y, '*', label="Polynomial")

 coeffs=  [6.85869364,     -92.86678553,  343.39375022,           -555.52532934,  434.18179364,
     -152.82724751,     9.71300951,   21.68653301,  -35.62838377,   28.3985976,
      27.04762122]
 new_testy = []
 for xi in arrlog:
 total = 0
    for i,v in enumerate(coeffs[::-1]):
       #print (v)
         total += v*xi**i
    new_testy.append(total)          
 plt.semilogx(arr, new_testy, 'o', label="Polynomial")         
 plt.legend(loc=2)
 plt.show()