一、實驗目的
掌握最小二乘法擬合離散數據,多項式函數形式擬合曲線以及可以其他可以通過變量變換轉化為多項式的擬合曲線目前待實現功能:
1. 最小二乘法的基本實現。
2. 用不同數據量,不同參數,不同的多項式階數,比較實驗效果。
3. 語言python。
二、實驗原理
最小二乘法(又稱最小平方法)是一種數學優化技術。它通過最小化誤差的平方和尋找數據的最佳函數匹配。利用最小二乘法可以簡便地求得未知的數據,並使得這些求得的數據與實際數據之間誤差的平方和為最小。最小二乘法還可用於曲線擬合。其他一些優化問題也可通過最小化能量或最大化熵用最小二乘法來表達。
三、實驗內容
求y=f(x)=sin(x)+h(x)在區間[0,10]上按101等距節點確定的離散數據點組(xi,yi)的直線擬合以及曲線擬合,其中是服從h(x)標准正態分布的噪聲擾動
四、程序實現
• 一次擬合:
1 import numpy as np 2 import matplotlib.pyplot as plt 3 import math 4 #定義x、y散點坐標 5 x = np.arange(0.0, 10.0,0.1) 6 x = np.array(x) 7 print('x is :\n',x) 8 num = np.sin(x)+np.random.randn(100) 9 y = np.array(num) 10 print('y is :\n',y) 11 f1 = np.polyfit(x, y, 1)#用1次多項式擬合,若要多次擬合,相應的改變這個常數即可 12 print('f1 is :\n',f1) 13 14 p1 = np.poly1d(f1) 15 print('p1 is :\n',p1) 16 17 #也可使用yvals=np.polyval(f1, x) 18 yvals = p1(x) #擬合y值 19 print('yvals is :\n',yvals) 20 #繪圖 21 plot1 = plt.plot(x, y, 's',label='original values',color="blue") 22 plot2 = plt.plot(x, yvals, 'r',label='polyfit values',color="red") 23 plt.xlabel('x') 24 plt.ylabel('y') 25 plt.legend(loc=4) #指定legend的位置右下角 26 plt.title('polyfitting') 27 plt.show()
運行結果:
所得圖形:
• 曲線擬合(用a*sin(x)+b擬合):
1 import numpy as np 2 import matplotlib.pyplot as plt 3 import math 4 from scipy.optimize import curve_fit 5 6 #自定義函數 7 def func(x, a, b): 8 return a*np.sin(x)+b 9 10 #定義x、y散點坐標 11 x = np.arange(0.0, 10.0,0.1) 12 x = np.array(x) 13 num = np.sin(x)+np.random.randn(100) 14 y = np.array(num) 15 16 #非線性最小二乘法擬合 17 popt, pcov = curve_fit(func, x, y) 18 #獲取popt里面是擬合系數 19 print(popt) 20 a = popt[0] 21 b = popt[1] 22 #c = popt[2] 23 #d = popt[3] 24 #e = popt[4] 25 yvals = func(x,a,b) #擬合y值 26 print('popt:', popt) 27 print('系數a:', a) 28 print('系數b:', b) 29 #print('系數c:', c) 30 #print('系數d:', d) 31 #print('系數e:', e) 32 print('系數pcov:', pcov)#方差 33 print('系數yvals:', yvals)#x代入擬合出的函數得到的函數值 34 #繪圖 35 plot1 = plt.plot(x, y, 's',label='original values',color="purple") 36 x_test = np.arange(0.0, 10.0, 0.01) 37 y_test = func(x_test,a,b) 38 plot2 = plt.plot(x_test, y_test, 'r',label='polyfit values',color="red") 39 plt.xlabel('x') 40 plt.ylabel('y') 41 plt.legend(loc=4) #指定legend的位置右下角 42 plt.title('curve_fit') 43 plt.show()
運行結果
所得圖形:
•曲線擬合(用a*np.sin(b*x+c)+d擬合):
1 import numpy as np 2 import matplotlib.pyplot as plt 3 import math 4 from scipy.optimize import curve_fit 5 6 #自定義函數 7 def func(x, a, b, c, d): 8 return a*np.sin(b*x+c)+d 9 10 #定義x、y散點坐標 11 x = np.arange(0.0, 10.0,0.1) 12 x = np.array(x) 13 num = np.sin(x)+np.random.randn(100) 14 y = np.array(num) 15 16 #非線性最小二乘法擬合 17 popt, pcov = curve_fit(func, x, y) 18 #獲取popt里面是擬合系數 19 print(popt) 20 a = popt[0] 21 b = popt[1] 22 c = popt[2] 23 d = popt[3] 24 yvals = func(x,a,b,c,d) #擬合y值 25 print('popt:', popt) 26 print('系數a:', a) 27 print('系數b:', b) 28 print('系數c:', c) 29 print('系數d:', d) 30 print('系數pcov:', pcov)#方差 31 print('系數yvals:', yvals)#x代入擬合出的函數得到的函數值 32 #繪圖 33 plot1 = plt.plot(x, y, 's',label='original values',color='orange') 34 x_test = np.arange(0.0, 10.0, 0.01) 35 y_test = func(x_test,a,b,c,d) 36 plot2 = plt.plot(x_test, y_test, 'r',label='polyfit values',color='brown') 37 plt.xlabel('x') 38 plt.ylabel('y') 39 plt.legend(loc=4) #指定legend的位置右下角 40 plt.title('curve_fit') 41 plt.show()
運行結果:
所得圖形:
•自定義函數實現:
1 import numpy as np 2 import matplotlib.pyplot as plt 3 import math 4 from scipy.optimize import curve_fit 5 6 #自定義函數 7 def func(x, a0,a1,a2,a3,a4,a5,a6,a7,a8,b1,b2,b3,b4,b5,b6,b7,b8,w): 8 return a0 + a1*np.cos(x*w) + b1*np.sin(x*w) + \ 9 a2*np.cos(2*x*w) + b2*np.sin(2*x*w) + a3*np.cos(3*x*w) + b3*np.sin(3*x*w) + \ 10 a4*np.cos(4*x*w) + b4*np.sin(4*x*w) + a5*np.cos(5*x*w) + b5*np.sin(5*x*w) + \ 11 a6*np.cos(6*x*w) + b6*np.sin(6*x*w) + a7*np.cos(7*x*w) + b7*np.sin(7*x*w) + \ 12 a8*np.cos(8*x*w) + b8*np.sin(8*x*w) 13 14 #定義x、y散點坐標 15 x = np.arange(0.0, 10.0,0.1) 16 x = np.array(x) 17 num = np.sin(x)+np.random.randn(100) 18 y = np.array(num) 19 20 #非線性最小二乘法擬合 21 popt, pcov = curve_fit(func, x, y) 22 #獲取popt里面是擬合系數 23 print(popt) 24 a0 = popt[0] 25 a1 = popt[1] 26 a2 = popt[2] 27 a3 = popt[3] 28 a4 = popt[4] 29 a5 = popt[5] 30 a6 = popt[6] 31 a7 = popt[7] 32 a8 = popt[8] 33 b1 = popt[9] 34 b2 = popt[10] 35 b3 = popt[11] 36 b4 = popt[12] 37 b5 = popt[13] 38 b6 = popt[14] 39 b7 = popt[15] 40 b8 = popt[16] 41 w = popt[17] 42 yvals = func(x,a0,a1,a2,a3,a4,a5,a6,a7,a8,b1,b2,b3,b4,b5,b6,b7,b8,w) #擬合y值 43 print('popt:', popt) 44 print('系數a0:', a0) 45 print('系數a1:', a1) 46 print('系數a2:', a2) 47 print('系數a3:', a3) 48 print('系數a4:', a4) 49 print('系數a5:', a5) 50 print('系數a6:', a6) 51 print('系數a7:', a7) 52 print('系數a8:', a8) 53 print('系數b1:', b1) 54 print('系數b2:', b2) 55 print('系數b3:', b3) 56 print('系數b4:', b4) 57 print('系數b5:', b5) 58 print('系數b6:', b6) 59 print('系數b7:', b7) 60 print('系數b8:', b8) 61 print('系數w:', w) 62 print('系數pcov:', pcov)#方差 63 print('系數yvals:', yvals)#x代入擬合出的函數得到的函數值 64 #繪圖 65 plot1 = plt.plot(x, y, 's',label='original values',color='yellow') 66 x_test = np.arange(0.0, 10.0, 0.01) 67 y_test = func(x_test,a0,a1,a2,a3,a4,a5,a6,a7,a8,b1,b2,b3,b4,b5,b6,b7,b8,w) 68 plot2 = plt.plot(x_test, y_test, 'r',label='polyfit values',color='blue') 69 plt.xlabel('x') 70 plt.ylabel('y') 71 plt.legend(loc=4) #指定legend的位置右下角 72 plt.title('curve_fit') 73 plt.show()
實現結果:
所得圖形:
心得體會
通過本次實驗,我對MATLAB的操作更加熟悉,也對本學期正在學習的Python有了更深層次的認識,對着兩種編程軟件更加熟悉。最重要的是:對最小二乘法理解深入,以及可以應用推廣,對數值分析理論的學習有很重要的作用,總而言之收獲頗多。