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函数求解其拟合直线的代码如下:
###最小二乘法试验###
import numpy as np
from scipy.optimize import leastsq
###采样点(Xi,Yi)###
Xi=np.array([8.19,2.72,6.39,8.71,4.7,2.66,3.78])
Yi=np.array([7.01,2.78,6.47,6.71,4.1,4.23,4.05])
###需要拟合的函数func及误差error###
def func(p,x):
k,b=p
return k*x+b
def error(p,x,y,s):
print s
return func(p,x)-y #x、y都是列表,故返回值也是个列表
#TEST
p0=[100,2]
#print( error(p0,Xi,Yi) )
###主函数从此开始###
s="Test the number of iteration" #试验最小二乘法函数leastsq得调用几次error函数才能找到使得均方误差之和最小的k、b
Para=leastsq(error,p0,args=(Xi,Yi,s)) #把error函数中除了p以外的参数打包到args中
k,b=Para[0<