一、实验目的
掌握最小二乘法拟合离散数据,多项式函数形式拟合曲线以及可以其他可以通过变量变换转化为多项式的拟合曲线目前待实现功能:
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 : ',x) 8 num = np.sin(x)+np.random.randn(100) 9 y = np.array(num) 10 print('y is : ',y) 11 f1 = np.polyfit(x, y, 1)#用1次多项式拟合,若要多次拟合,相应的改变这个常数即可 12 print('f1 is : ',f1) 13 14 p1 = np.poly1d(f1) 15 print('p1 is : ',p1) 16 17 #也可使用yvals=np.polyval(f1, x) 18 yvals = p1(x) #拟合y值 19 print('yvals is : ',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有了更深层次的认识,对着两种编程软件更加熟悉。最重要的是:对最小二乘法理解深入,以及可以应用推广,对数值分析理论的学习有很重要的作用,总而言之收获颇多。