futurechao的个人空间 https://blog.eetop.cn/1227585 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

Python科学计算技巧积累六——拟合sine函数

已有 5318 次阅读| 2015-9-28 13:49 |个人分类:编程语言

Python也可以像MATLAB一样进行函数拟合,在拟合线性函数时numpy.polyfit使用很方便.但是在拟合非线性函数时,Python就不如MATLAB使用方便快捷。不过Scipy.optimize.curve_fit也提供了基于最小二乘法的拟合,只是需要自己定义函数,不如MATLAB的cftool工具箱方便。

本文将就拟合sine函数为例,对照程序,总结scipy.optimize.curve_fit的技巧,以供以后使用时参考。

首先程序开头少不了调用函数库
import scipy as sp

from scipy.optimize import curve_fit # 在拟合时需要此函数库

import numpy as np

import matplotlib.pylab as plt

from math import *

plt.close('all')


然后读取数据并作图,本例中使用的横坐标数据为L,纵坐标数据为P

filename = 'coupler_2D_couplingLength.txt'

L = []

P = []

with open(filename, 'r') as file_to_read:

     while True:

         lines = file_to_read.readline()

         if not lines:

             break

             pass

         L_tmp, P_tmp = [float(i) for i in lines.split()]

         L.append(L_tmp)

         P.append(P_tmp)

         pass

L = np.array(L)

P = np.array(P)


fig = plt.figure(figsize=(3.2,2.8))

plt.plot(L, P, linewidth = 2)

#plt.legend(fontsize = 'xx-small')

plt.xlabel('Waveguide length ($\mu m$)', fontsize = 12)

plt.ylabel('Normalized Power', fontsize = 12)

plt.title('Original input', fontsize = 12)

plt.rc('xtick', labelsize = 9)

plt.rc('ytick', labelsize = 9)

plt.tight_layout()

plt.show()


原始数据的图形如下:

下面对数据进行拟合,以得到精确的振幅,频率,相位和常数项。我们定义目标函数是sine函数:


# 定义希望拟合的函数类型

def fitSine(x, A, f, phi, c):

     return A*np.cos(2*pi*f*x+phi) + c


# 进行拟合

fit_opt, fit_cov = curve_fit(fitSine, L, P)


# 提取拟合数据

coe_A = fit_opt[0]

coe_f = fit_opt[1]

coe_phi = fit_opt[2]

coe_c = fit_opt[3]

fitted_P = fitSine(L, coe_A, coe_f, coe_phi, coe_c)


# 作图

fig = plt.figure(figsize=(3.2,2.8))

plt.plot(L, fitted_P, linewidth = 2)

#plt.legend(fontsize = 'xx-small')

plt.xlabel('Waveguide length ($\mu m$)', fontsize = 12)

plt.ylabel('Normalized Power', fontsize = 12)

plt.title('Fitted curve', fontsize = 12)

plt.rc('xtick', labelsize = 9)

plt.rc('ytick', labelsize = 9)

plt.tight_layout()

plt.show()


得到的图像如下:

显然拟合的图像和原图相差甚远,这主要是因为默认的初始值没有选好。为了解决这个问题,我们可以手动输入初始值以提高精度。


对源代码进行如下修改:

A_g = input('Estimated amplitude: ')

f_g = input('Estimated frequency: ')

phi_g = input('Estimated phase: ')

c_g = input('Estimated offset: ')

a_guess = [A_g,f_g,phi_g, c_g]

fit_opt, fit_cov = curve_fit(fitSine, L, P,p0=a_guess)


在程序运行时,终端会提示输入估计值,假设我们采用以下估计值:

a_g = 0.5

f_g = 3e-3

phi_g = 0

c_g  = 0.5


得到的图像如下:

拟合得到的数据如下:

A = 0.499733913

f = 0.00287385

phi = -2.60167e-7

c = 0.4999


经过初始值预测后的拟合就准确了很多。


参考资料: https://faculty1.coloradocollege.edu/~sburns/toolbox/DataFitting.html




点赞

发表评论 评论 (2 个评论)

回复 S小凡 2015-10-9 10:30
:handshake :loveliness:

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 2

    粉丝
  • 0

    好友
  • 5

    获赞
  • 9

    评论
  • 553

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-17 02:23 , Processed in 0.009883 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部