Python闲谈(二)聊聊最小二乘法以及leastsq函数

1 最小二乘法概述

自从开始做毕设以来,发现自己无时无刻不在接触最小二乘法。从求解线性透视图中的消失点,m元n次函数的拟合,包括后来学到的神经网络,其思想归根结底全都是最小二乘法。

1-1 “多线→一点”视角与“多点→一线”视角

最小二乘法非常简单,我把它分成两种视角描述:

(1)已知多条近似交汇于同一个点的直线,想求解出一个近似交点:寻找到一个距离所有直线距离平方和最小的点,该点即最小二乘解;

(2)已知多个近似分布于同一直线上的点,想拟合出一个直线方程:设该直线方程为y=kx+b,调整参数k和b,使得所有点到该直线的距离平方之和最小,设此时满足要求的k=k0,b=b0,则直线方程为y=k0x+b0。

1-2 思维拓展

这只是举了两个简单的例子,其实在现实生活中我们可以利用最小二乘法解决更为复杂的问题。比方说有一个未知系数的二元二次函数f(x,y)=w0x^2+w1y^2+w2xy+w3x+w4y+w5,这里w0~w5为未知的参数,为了确定下来这些参数,将会给定一些样本点(xi,yi,f(xi,yi)),然后通过调整这些参数,找到这样一组w0~w5,使得这些所有的样本点距离函数f(x,y)的距离平方之和最小。至于具体用何种方法来调整这些参数呢?有一种非常普遍的方法叫“梯度下降法”,它可以保证每一步调整参数,都使得f(x,y)朝比当前值更小的方向走,只要步长α选取合适,我们就可以达成这种目的。

而这里不得不提的就是神经网络了。神经网络其实就是不断调整权值w和偏置b,来使得cost函数最小,从这个意义上来讲它还是属于最小二乘法。更为可爱的一点是,神经网络的调参用到的仍是梯度下降法,其中最常用的当属随机梯度下降法。而后面伟大的bp算法,其实就是为了给梯度下降法做个铺垫而已,bp算法的结果是cost函数对全部权值和全部偏置的偏导,而得知了这些偏导,对于各个权值w和偏置b该走向何方就指明了方向。

因此,最小二乘法在某种程度上无异于机器学习中基础中的基础,且具有相当重要的地位。至于上面所说的“梯度下降法”以及“利用最小二乘法求解二元二次函数的w0~w5”,我将会在后面的博客中进行更加详细的探讨。

2 scipy库中的leastsq函数

当然,最小二乘法本身实现起来也是不难的,就如我们上面所说的不断调整参数,然后令误差函数Err不断减小就行了。我们将在下一次博客中详细说明如何利用梯度下降法来完成这个目标。

而在本篇博客中,我们介绍一个scipy库中的函数,叫leastsq,它可以省去中间那些具体的求解步骤,只需要输入一系列样本点,给出待求函数的基本形状(如我刚才所说,二元二次函数就是一种形状——f(x,y)=w0x^2+w1y^2+w2xy+w3x+w4y+w5,在形状给定后,我们只需要求解相应的系数w0~w6),即可得到相应的参数。至于中间到底是怎么求的,这一部分内容就像一个黑箱一样。

2-1 函数形为y=kx+b

这一次我们给出函数形y=kx+b。这种情况下,待确定的参数只有两个:k和b。

此时给出7个样本点如下:

1 Xi=np.array([8.19,2.72,6.39,8.71,4.7,2.66,3.78])
2 Yi=np.array([7.01,2.78,6.47,6.71,4.1,4.23,4.05])

则使用leastsq函数求解其拟合直线的代码如下:

 1 ###最小二乘法试验###
 2 import numpy as np
 3 from scipy.optimize import leastsq
 4
 5 ###采样点(Xi,Yi)###
 6 Xi=np.array([8.19,2.72,6.39,8.71,4.7,2.66,3.78])
 7 Yi=np.array([7.01,2.78,6.47,6.71,4.1,4.23,4.05])
 8
 9 ###需要拟合的函数func及误差error###
10 def func(p,x):
11     k,b=p
12     return k*x+b
13
14 def error(p,x,y,s):
15     print s
16     return func(p,x)-y #x、y都是列表,故返回值也是个列表
17
18 #TEST
19 p0=[100,2]
20 #print( error(p0,Xi,Yi) )
21
22 ###主函数从此开始###
23 s="Test the number of iteration" #试验最小二乘法函数leastsq得调用几次error函数才能找到使得均方误差之和最小的k、b
24 Para=leastsq(error,p0,args=(Xi,Yi,s)) #把error函数中除了p以外的参数打包到args中
25 k,b=Para[0]
26 print"k=",k,‘\n‘,"b=",b
27
28 ###绘图,看拟合效果###
29 import matplotlib.pyplot as plt
30
31 plt.figure(figsize=(8,6))
32 plt.scatter(Xi,Yi,color="red",label="Sample Point",linewidth=3) #画样本点
33 x=np.linspace(0,10,1000)
34 y=k*x+b
35 plt.plot(x,y,color="orange",label="Fitting Line",linewidth=2) #画拟合直线
36 plt.legend()
37 plt.show()

我把里面需要注意的点提点如下:

1、p0里放的是k、b的初始值,这个值可以随意指定。往后随着迭代次数增加,k、b将会不断变化,使得error函数的值越来越小。

2、func函数里指出了待拟合函数的函数形状。

3、error函数为误差函数,我们的目标就是不断调整k和b使得error不断减小。这里的error函数和神经网络中常说的cost函数实际上是一回事,只不过这里更简单些而已。

4、必须注意一点,传入leastsq函数的参数可以有多个,但必须把参数的初始值p0和其它参数分开放。其它参数应打包到args中。

5、leastsq的返回值是一个tuple,它里面有两个元素,第一个元素是k、b的求解结果,第二个元素我暂时也不知道是什么意思,先留下来。

其拟合效果图如下:

2-2 函数形为y=ax^2+bx+c

这一次我们给出函数形y=ax^2+bx+c。这种情况下,待确定的参数有3个:a,b和c。

此时给出7个样本点如下:

1 Xi=np.array([0,1,2,3,-1,-2,-3])
2 Yi=np.array([-1.21,1.9,3.2,10.3,2.2,3.71,8.7])

这一次的代码与2-1差不多,除了把待求参数再增加一个,换了一下训练样本,换了一下func中给出的函数形,几乎没有任何变化。

 1 ###最小二乘法试验###
 2 import numpy as np
 3 from scipy.optimize import leastsq
 4
 5 ###采样点(Xi,Yi)###
 6 Xi=np.array([0,1,2,3,-1,-2,-3])
 7 Yi=np.array([-1.21,1.9,3.2,10.3,2.2,3.71,8.7])
 8
 9 ###需要拟合的函数func及误差error###
10 def func(p,x):
11     a,b,c=p
12     return a*x**2+b*x+c
13
14 def error(p,x,y,s):
15     print s
16     return func(p,x)-y #x、y都是列表,故返回值也是个列表
17
18 #TEST
19 p0=[5,2,10]
20 #print( error(p0,Xi,Yi) )
21
22 ###主函数从此开始###
23 s="Test the number of iteration" #试验最小二乘法函数leastsq得调用几次error函数才能找到使得均方误差之和最小的a~c
24 Para=leastsq(error,p0,args=(Xi,Yi,s)) #把error函数中除了p以外的参数打包到args中
25 a,b,c=Para[0]
26 print"a=",a,‘\n‘,"b=",b,"c=",c
27
28 ###绘图,看拟合效果###
29 import matplotlib.pyplot as plt
30
31 plt.figure(figsize=(8,6))
32 plt.scatter(Xi,Yi,color="red",label="Sample Point",linewidth=3) #画样本点
33 x=np.linspace(-5,5,1000)
34 y=a*x**2+b*x+c
35 plt.plot(x,y,color="orange",label="Fitting Curve",linewidth=2) #画拟合曲线
36 plt.legend()
37 plt.show()

不过我们发现,它依旧能够非常顺利地解出待求的三个参数。其拟合情况如图所示:

2-3 结语

本次博客给出了最小二乘法的Python实现方法,它用到了scipy库中的leastsq函数。在上面我们给出了两个实例,分别实现了对一元一次函数的拟合和一元二次函数的拟合,而事实上,对于函数并不一定得是一元函数,对于更多元的函数也同样能够利用最小二乘法完成拟合工作,不过随着元和次的增加,待求参数也就越来越多了,比方说二元二次函数就有6个待求参数w0~w6。

然为了更好地理解神经网络的训练算法,并不建议直接使用leastsq函数完成对未知参数的求解,因此在以后的博客中我会详细说明如何利用梯度下降法来求解误差函数的最小值。

3 下面要写的博客

1、梯度下降法(什么是梯度下降法,如何使用梯度下降法求一元二次函数最小值)

2、利用梯度下降法拟合二元二次函数(即求解w0~w5,相当于对梯度下降法的一个应用)

3、最小二乘法求解机器学习中cost函数最小值(什么是cost函数,并利用leastsq求解误差函数最小值)

2016.5.14

by 悠望南山

时间: 2025-02-01 08:56:55

Python闲谈(二)聊聊最小二乘法以及leastsq函数的相关文章

OpenCV for Python 学习 (二 事件与回调函数)

今天主要看了OpenCV中的事件以及回调函数,这么说可能不准确,主要是下面这两个函数(OpenCV中还有很多这些函数,可以在 http://docs.opencv.org/trunk/modules/highgui/doc/user_interface.html 找到,就不一一列举了),然后自己做了一个简单的绘图程序 函数如下: cv2.setMouseCallback(windowName, onMouse[, param]) cv2.createTrackbar(trackbarName,

PYTHON练习题 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数。

Python 练习 二. 使用random中的randint函数随机生成一个1~100之间的预设整数让用户键盘输入所猜的数,如果大于预设的数,屏幕显示"太大了,请重新输入"如果小于预设的数,屏幕显示"太小了,请重新输入"如此循环,直到猜中,显示"恭喜你,猜中了!共猜了N次"N为用户猜测次数. 答案: import random def guess_number(): true_num = random.randint(1, 100) user_n

python闲谈--内置高级函数

1.map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 假设用户输入的英文名字不规范,没有按照首字母大写,后续字母小写的规则,请利用map()函数,把一个list(包含若干不规范的英文名字)变成一个包含规范英文名字的list: # -*- coding:gbk -*-def format_name(s):    return s[0].upper() + s[1:].lower(

Python中如何使用最小二乘法

之所以说"使用"而不是"实现",是因为python的相关类库已经帮我们实现了具体算法,而我们只要学会使用就可以了.随着对技术的逐渐掌握及积累,当类库中的算法已经无法满足自身需求的时候,我们也可以尝试通过自己的方式实现各种算法. 言归正传,什么是"最小二乘法"呢? 定义:最小二乘法(又称最小平方法)是一种数学优化技术,它通过最小化误差的平方和寻找数据的最佳函数匹配. 作用:利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误

机器学习:Python中如何使用最小二乘法

之所以说"使用"而不是"实现",是因为python的相关类库已经帮我们实现了具体算法,而我们只要学会使用就可以了.随着对技术的逐渐掌握及积累,当类库中的算法已经无法满足自身需求的时候,我们也可以尝试通过自己的方式实现各种算法. 言归正传,什么是"最小二乘法"呢? 定义:最小二乘法(又称最小平方法)是一种数学优化技术,它通过最小化误差的平方和寻找数据的最佳函数匹配. 作用:利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误

python中matplotlib实现最小二乘法拟合的过程详解

这篇文章主要给大家介绍了关于python中matplotlib实现最小二乘法拟合的相关资料,文中通过示例代码详细介绍了关于最小二乘法拟合直线和最小二乘法拟合曲线的实现过程,需要的朋友可以参考借鉴,下面来一起看看吧. 前言 最小二乘法Least Square Method,做为分类回归算法的基础,有着悠久的历史(由马里·勒让德于1806年提出).它通过最小化误差的平方和寻找数据的最佳函数匹配.利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小.最小二乘法还

python基础二

一.字典类型 *)字典是python中唯一的映射类型 ,key-value(哈希表),字典对象是可变的,但key必须用不可变对象. *)字典的创建和字典值得访问 ##字典的内容在查看时不能通过索引来进行查看 *)内建方法:fromkeys 字典中的key有相同的value值,默认为None *)字典的循环遍历访问 *)字典中key-value的添加 dic[key] = value ##通过字典的添加发现,字典是无序的数据类型 *)字典的删除 **)根据key值删除字典的元素 **)随机删除字典

[python] 之all()和any()内置函数

在python 2.5版本以上开始引入,其基本使用方法如下: 一.all()内置函数 语法:all(iter) 说明: 1. iter为可迭代对象,比如列表,元组,字符串... 2. 若iter中的每一个元素(全部)都为布尔真(或布尔值意味着False的一些元素,比如'0','False',空字符' ' 等)时,返回True 3. 空的列表或元组,也返回True 二.any()内置函数 语法:any(iter) 说明: 1. iter为可迭代对象,比如列表,元组,字符串... 2. 若iter中

【美妙的Python之二】Python初步

美妙的Python之Python起步 简而言之: Python 是能你无限惊喜的语言,与众不同.           1.动态类型:         Python是一种动态类型语言,不需要预先声明变量的类型,变量的类型和值在赋值那一刻动态地初始化.这一点与C/C++,Java等静态类型语言完全不同,静态类型在编译阶段就必须显示的声明变量的类型,动态类似在运行时才确定变量的类型.        变量a动态地初始化为int类型,并赋值2014;        变量msg则动态初始化为str类型,并赋