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 给出的代码,我对结果很满意。
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()
我有以下 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 给出的代码,我对结果很满意。
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()