Python最小二乘法拟合与作图

最小二乘法拟合

在函数拟合中,如果用p表示函数中需要确定的参数,那么目标就是找到一组p,使得下面函数S的值最小:

最小二乘

这种算法称为最小二乘法拟合。Python的Scipy数值计算库中的optimize模块提供了leastsq()函数,可以对数据进行最小二乘拟合计算。

此处利用该函数对一段弧线使用圆方程进行了拟合,并通过Matplotlib模块进行了作图,程序内容如下:

#使用最小二乘法拟合圆方程
import numpy as np
from scipy.optimize import leastsq
from pylab import *

x,y=np.loadtxt('num.dat',delimiter=' ',dtype=float,usecols=(0,1),unpack=True)

#for i in x:
#    print i
#for j in y:
#    print j

def residuals(p):
    a,b,r=p
    return r**2-(y-b)**2-(x-a)**2
    
result=leastsq(residuals,[1,1,1])
a,b,r=result[0]
print "a=",a,"b=",b,"r=",r

plot(x,y,color="red",label="origin",linewidth=2)
yfit=sqrt(r**2-(x-a)**2)+b
plot(x,yfit,"b--",label="fit",linewidth=2)
legend(loc="upper right",frameon=False)
annotate('(x-112.892403261)$^2$+(y+58.8238235027)$^2$=110.123575696$^2$',xy=(40,15))
annotate('R=110.123575696',xy=(100,10))


show()

拟合过程说明

导入模块

Python的使用中需要导入相应的模块,此处首先用import语句

import numpy as np
from scipy.optimize import leastsq
from pylab import *

分别导入了numpy, leastsq与pylab模块,其中numpy模块常用用与数组类型的建立,读入等过程。leastsq则为最小二乘法拟合函数。pylab是绘图模块。

读入数据

接下来我们需要读入需要进行拟合的数据,这里使用了numpy.loadtxt()函数:

x,y=np.loadtxt('num.dat',delimiter=' ',dtype=float,usecols=(0,1),unpack=True)

其参数有:

fname:读入文件名,也可省略参数直接写'filename'。
dtype:读入后数据的存放类型,默认为float。
comments:注释符号,读入时忽略以该符号开头的行,默认为'#'。
delimiter:分隔符,存在多列数据时以该符号进行分割,默认为空格。
converters:将列号映射到所需值,可以为遗失的数据提供默认值,默认为不开启。
skiprows:读入时跳过前多少行,默认为0。
usecols:读取第多少列,从0开始计数,可跳跃读取,如usecols=(0,3,8)。1.11.0版更新,取单独一列时可使用usecols=3,并非必须用元组的形式。
unpack:布尔值,如果为真,则对返回的数组进行置换,以便可以使用x,y,z = loadtxt(…)来解压缩数组。当与结构化数据类型一起使用时,将为每个字段返回数组。默认为False。
ndmin:返回的数组将至少具有ndmin维度。否则,一维轴将被压缩。合法值:0(默认值)、1或2。1.6.0版本中的新功能。
encoding:用于解码。1.14.0版本中的新功能。(不是很理解英文原文的意思)
max_rows:skiprows后读入的最大行数,默认读取全部。1.16.0版本中的新功能。

进行拟合

进行拟合时,首先我们需要定义一个目标函数。对于圆的方程,我们需要圆心坐标(a,b)以及半径r三个参数,方便起见用p来存储:

def residuals(p):
    a,b,r=p
    return r**2-(y-b)**2-(x-a)**2

紧接着就可以进行拟合了,leastsq()函数需要至少提供拟合的函数名与参数的初始值:

result=leastsq(residuals,[1,1,1])
a,b,r=result[0]
print "a=",a,"b=",b,"r=",r

返回的结果为一数组,分别为拟合得到的参数与其误差值等,这里只取拟合参数值。

leastsq()的参数具体有:

func:函数名,该函数应至少具有一个参数并返回多个浮点数,不能返回NaNs
x0:需拟合参数的初始值
Dfun:用行间导数计算func的雅可比行列的函数或方法。如果为空,则估计雅可比行列式。
full_output:布尔值,非零以返回所有可选输出。
col_deriv:布尔值,非零以指定雅可比函数计算列中的导数(更快,因为没有转置操作)。
ftol:平方和中所需的相对误差。
xtol:近似解中所需的相对误差。
gtol:函数向量和雅可比行列之间所需的正交性。
maxfev:对函数的最大调用次数。如果提供了Dfun,则默认maxfev100*(N+1),其中N是x0中元素的数量,否则默认maxfev200*(N+1)
epsfn:用于确定雅可比行列式的前向误差合适步长的变量(对于Dfun=None)。通常,实际步长将为sqrt(epsfcn)*x如果epsfcn小于机器精度,则假定相对误差为机器精度的数量级。
factor:确定初始步长的参数(factor * || diag * x||),应在(0.1,100)的区间内。
diag:N个正条目,用作变量的比例因子。

输出选项有:

x:解(或拟合不成功时的最后一次迭代的结果)。
cov_x:使用fjacipvt可选输出来构建解决方案周围雅可比的估计值。如果遇到奇异矩阵则表示无(表示在某个方向上的曲率非常平坦)。该矩阵必须乘以残差方差,得到参数估计的协方差.详见curve_fit。

infodict:密钥s的可选输出字典:

  • nfev:函数调用的次数。
  • fvec:在输出处评估函数。
  • fjac:列存储最终近似雅可比矩阵的QR分解的R矩阵的排列。 与ipvt一起,估计的协方差的可能近似。
  • ipvt:长度为N的整数数组,它定义了一个置换矩阵p,使得fjac*p=q*r,其中r是上三角形,对角元素的幅度不增大。 p的列j是单位矩阵的列ipvt(j)。
  • qtf:向量(转置(q)*fvec)。

mesg:一个字符串消息,提供有关失败原因的信息。
ies:整数标志。如果它等于1,2,3或4,则发现解决方案。否则,找不到解决方案。在任何一种情况下,可选的输出变量mesg都会提供更多信息。

对结果作图

最后我们可以将原数据与拟合结果一同做成线状图,可采用pylab.plot()函数:

plot(x,y,color="red",label="origin",linewidth=2)
plot(x,yfit,"b--",label="fit",linewidth=2)
legend(loc="upper right",frameon=False)
annotate('R=110.123575696',xy=(100,10))
show()

pylab.plot()函数需提供两列数组作为输入,其他参数可调控线条颜色,形状,粗细以及对应名称等性质。视需求而定,此处不做详解。

pylab.legend()函数可以调控图像标签的位置,有无边框等性质。

pylab.annotate()函数设置注释,需至少提供注释内容与放置位置坐标的参数。

pylab.show()函数用于显示图像。

最终结果如下图所示:

拟合结果

参考资料

用Python作科学计算

numpy.loadtxt

scipy.optimize.leastsq

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容