大多数的回归问题,都可以使用最小二乘法来求解参数,而求解参数的过程又通常依赖梯度下降法。不仅是回归问题,很多机器学习都是基于梯度下降来实现参数优化,因此梯度下降可以说是机器学习的核心算法之一。简单地说梯度下降利用导数,通过不断迭代,经过有限次的运算,逐渐逼近最优解。
1. 一元回归与最小二乘
直接看吴恩达老师课程中的例子。现在有一些房价和面积的数据(x,y),想找出他们之间的关系。
我们可以大概画出散点图,通过图形分布,假设他们之间是线性关系。那么这个例子可以抽象为,求一个方程f(x) = k*x+b,使预测值f(x)与真实值y尽量接近。
如何算是接近?我们定义一个新的函数来判断接近程度。这个函数叫做损失函数,用差平方来表示,[f(x)-y]2。它反映了预测值与真实值的偏离程度。差平方和则反映了所有样本的偏离大小。将参数k和b用p取代,假设共有m个样本,那么拟合问题就成了找一组p值,使如下函数值最小。
这种拟合方法称为最小二乘法。现在我们不继续深究,因为这个一元问题用Excel就能搞定了:
2. 多元回归与梯度下降
一元线性回归只是其他更复杂模型中的一个特例,实际数据也往往并不会这么简单。现在我们给数据增加一个维度,探究一下房间数量、房屋面积和价格间的关系。
根据上面的思路,首先假设还是线性关系。将参数统一表示为θn(或叫做权重,相当于一元中的k,b),xn为数据特征,本例中两个数据特征分别为面积和房间数量。用多元回归对房价进行拟合。这里设x0=1。
同样,引入经验风险J(θ),相当于上文中的S(P),表示数据总体的误差。前面乘以0.5,是方便后面的求导运算:
为了使决策函数更接近真实值之间的关系,经验风险越小越好。到这里,最优问题就成了求最小值问题。J(θ)这个函数可以看成是这样的。
如何到达最低点,从而使J(θ)最小呢?接下来就需要梯度下降法了。首先,随机给定一组θ值,得到一个解。在这个解的基础上进行优化,让θj沿着J(θ)下降最快的方向,也就是导数的反方向移动一小步,得到一个新的θj,再继续优化,重复上述过程,多次调整后,最终沿着“path”,达到最低点。表达式如下。
其中“α”叫做学习率,代表了每一次优化的步长。步长太大,容易直接跳过最优解,步长太小,迭代次数过多,学习效率降低。“:=”表示从右向左赋值,新产生的值会再次迭代,直到求出最小值。
对θj求偏导数,根据加减法则及链式求导法则得到以下等式:
最终梯度下降法表达式如下:
3. 回归问题的python实现
在python的scipy库中,提供了leastsq函数,直接实现此目的,语法如下:
scipy.optimize.leastsq(func,x0,args=(),……)
func:预测值与实际值的差,需要带有至少一个变量,并返回数值型数据。
x0:初始参数,作为学习的起点。格式为数组。
args:训练集。
leastsq函数的目标是,求得如下的一个值:
是不是很熟悉?把func(y)**2作为误差函数,再经过sum求和,就等于经验风险。即求一个y值,使经验风险J(θ)或S(p)最小。
Python实现过程分为以下四个步骤
(1)定义拟合函数
def f(x1, x2, p):
k0, k1, k2 = p
returnk0 +k1*x1 + k2*x2
(2)定义误差函数
def cost(p,x1,x2,y):
return y-f(x1,x2, p)
(3)初始化参数
p0=[1,1,1]
x1=np.array([2104,1600,2400,1416,3000])
x2=np.array([3,3,3,2,4])
y=np.array([400,330,369,232,540])
(4)用leastsq求解
arg = leastsq(cost,p0,args=(x1,x2,y))
print arg[0]
完整代码如下:
输出
[-7.04346018e+01 6.38433756e-02 1.03436047e+02]
4. 正规方程组
梯度下降法通过多次迭代,最终求出最优解。如果想一次性求出结果,也能够实现。即利用最优解处,导数为0特征直接求解。与梯度下降法类似,用x(i)列向量表示第i个数据里所有的变量特征,θ列向量表示每个特征对应的权重,y向量表示每组数据的实际输出。每个预测值和实际值的差用如下方程表示:
接着写出风险函数:
对风险函数求导:
并使导数等于0,即可能存在的最优解: