python数据挖掘学习笔记】十四.Scipy调用curve_fit实现曲线拟合

#2018-03-28 10:02:08 March Wednesday the 13 week, the 087 day SZ SSMR
python数据挖掘学习笔记】十四.Scipy调用curve_fit实现曲线拟合 

一. Scipy介绍
SciPy (pronounced "Sigh Pie") 是一个开源的数学、科学和工程计算包。它是一款方便、易于使用、专为科学和工程设计的Python工具包,包括统计、优化、整合、线性代数模块、傅里叶变换、信号和图像处理、常微分方程求解器等等。
Scipy优化和拟合采用的是optimize模块,该模块提供了函数最小值(标量或多维)、曲线拟合和寻找等式的根的有用算法。
下面将从实例进行详细介绍,包括:
        1.调用 numpy.polyfit() 函数实现一次二次多项式拟合;
        2.Pandas导入数据后,调用Scipy实现次方拟合;
        3.实现np.exp()形式e的次方拟合;
        4.实现三个参数的形式拟合;
        5.最后通过幂率图形分析介绍自己的一些想法和问题。
二. 曲线拟合


1.多项式拟合polynomial fitting

        首先通过numpy.arange定义x、y坐标,然后调用polyfit()函数进行3次多项式拟合,最后调用Matplotlib函数进行散点图绘制(x,y)坐标,并绘制预测的曲线。
        完整代码:
#encoding=utf-8  
import numpy as np
import matplotlib.pyplot as plt

#定义x、y散点坐标
x = np.arange(1, 16, 1)
print('x is :\n',x)
num = [4.00, 5.20, 5.900, 6.80, 7.34,
       8.57, 9.86, 10.12, 12.56, 14.32,
       15.42, 16.50, 18.92, 19.58, 20.00]
y = np.array(num)
print('y is :\n',y)
#用3次多项式拟合
f1 = np.polyfit(x, y, 3)
print('f1 is :\n',f1)

p1 = np.poly1d(f1)
print('p1 is :\n',p1)

#也可使用yvals=np.polyval(f1, x)
yvals = p1(x)  #拟合y值
print('yvals is :\n',yvals)
#绘图
plot1 = plt.plot(x, y, 's',label='original values')
plot2 = plt.plot(x, yvals, 'r',label='polyfit values')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc=4) #指定legend的位置右下角
plt.title('polyfitting')
plt.show()
plt.savefig('test.png')

输出:
x is :
 [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15]
y is :
 [  4.     5.2    5.9    6.8    7.34   8.57   9.86  10.12  12.56  14.32
  15.42  16.5   18.92  19.58  20.  ]
f1 is :
 [-0.00466922  0.13917511  0.04214103  4.31284982]
p1 is :
            3          2
-0.004669 x + 0.1392 x + 0.04214 x + 4.313
yvals is :
 [  4.48949673   4.91647852   5.56577986   6.40938541   7.41927982
   8.56744778   9.82587395  11.16654299  12.56143956  13.98254834
  15.40185398  16.79134116  18.12299454  19.36879879  20.50073856]
[Finished in 4.9s]
2.e的b/x次方拟合

        下面采用Scipy的curve_fit()对上面的数据进行e的b/x次方拟合。数据集如下:
#encoding=utf-8  
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

#自定义函数 e指数形式
def func(x, a, b):
    return a*np.exp(b/x)

#定义x、y散点坐标
x = np.arange(1, 16, 1)
num = [4.00, 5.20, 5.900, 6.80, 7.34,
       8.57, 9.86, 10.12, 12.56, 14.32,
       15.42, 16.50, 18.92, 19.58, 20.00]
y = np.array(num)

#非线性最小二乘法拟合
popt, pcov = curve_fit(func, x, y)
#获取popt里面是拟合系数
a = popt[0] 
b = popt[1]
yvals = func(x,a,b) #拟合y值
print('popt:', popt)
print('系数a:', a)
print('系数b:', b)
print('系数pcov:', pcov)
print('系数yvals:', yvals)
#绘图
plot1 = plt.plot(x, y, 's',label='original values')
plot2 = plt.plot(x, yvals, 'r',label='polyfit values')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc=4) #指定legend的位置右下角
plt.title('curve_fit')
plt.show()
plt.savefig('test2.png')

popt: [ 28.73385676  -6.533497  ]
系数a: 28.7338567619
系数b: -6.53349700023
系数pcov: [[ 11.50459022  -3.49473351]
 [ -3.49473351   1.23200917]]
系数yvals: [  0.04177652   1.09562788   3.25516763   5.61084794   7.77860258
   9.67127294  11.29905836  12.69729502  13.90338026  14.95022583
  15.86510166  16.67012212  17.3831164   18.01847731  18.58787783]


3.aX的b次方拟合


        第三种方法是通过Pandas导入数据,因为通常数据都会存储在csv、excel或数据库中,所以这里结合读写数据绘制a*x的b次方形式。
        假设本地存在一个data.csv文件,数据集如下图所示:
 最后完整的拟合代码如下所示:

#程序有问题:KeyError: 'x'
#encoding=utf-8  
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import pandas as pd  

#自定义函数 e指数形式
def func(x, a, b):
    return a*pow(x,b)

#导入数据及x、y散点坐标
data = pd.read_csv("data.csv")
#print(data)
#print(data.shape)    
#print(data.head(5)) #显示前5行数据
#KeyError: 'x'
x = data['x'] #获取x列
y = data['y'] #获取y列
print(x)
print(y)

#非线性最小二乘法拟合
popt, pcov = curve_fit(func, x, y)
#获取popt里面是拟合系数
a = popt[0] 
b = popt[1]
yvals = func(x,a,b) #拟合y值
print(u'系数a:', a)
print(u'系数b:', b)

#绘图
plot1 = plt.plot(x, y, 's',label='original values')
plot2 = plt.plot(x, yvals, 'r',label='polyfit values')
plt.xlabel('x')
plt.ylabel('y')
plt.legend(loc=4) #指定legend的位置右下角
plt.title('curve_fit')
plt.savefig('test3.png')
plt.show()


4.三个参数拟合

        最后介绍官方给出的实例,讲述传递三个参数,通常为 a*e(b/x)+c形式。
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a * np.exp(-b * x) + c

# define the data to be fit with some noise
xdata = np.linspace(0, 4, 50)       #产生0到4之间的50个等距离数字
print("xdata is:",xdata)
y = func(xdata, 2.5, 1.3, 0.5)          #y=  a*e(b/x)+c
print("y is:",y)
y_noise = 0.2 * np.random.normal(size=xdata.size)
print("y_noise is:",y_noise)
ydata = y + y_noise
print("ydata is:",ydata)
plt.plot(xdata, ydata, 'b-', label='data')

# Fit for the parameters a, b, c of the function `func`
popt, pcov = curve_fit(func, xdata, ydata)
print("popt is:", popt)
print("*popt is:", *popt)
plt.plot(xdata, func(xdata, *popt), 'r-', label='fit')

'''##########
a = popt[0] 
b = popt[1]
yvals = func(x,a,b) #拟合y值
plot2 = plt.plot(x, yvals, 'r',label='polyfit values')

'''################################


# Constrain the optimization to the region of ``0 < a < 3``, ``0 < b < 2``
# and ``0 < c < 1``:
popt, pcov = curve_fit(func, xdata, ydata, bounds=(0, [3., 2., 1.]))
plt.plot(xdata, func(xdata, *popt), 'g--', label='fit-with-bounds')

plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()






你可能感兴趣的:(学习总结)