回归问题提出
首先需要明确回归问题的根本目的在于预测。对于某个问题,一般我们不可能测量出每一种情况(工作量太大),故多是测量一组数据,基于此数据去预测其他未测量数据。
比如课程给出的房屋面积、房间数与价格的对应关系,如下表:
若要测量出所有情况,不知得测到猴年马月了。有了上面这一组测量数据,我们要估计出一套房子(如2800平方英尺5个房间)的价格,此时回归算法就可以荣耀登场了。
回归算法推导
有了上面这个问题,如何来估计房子的价格呢?首先需要建立模型,一种最简单的模型就是线性模型了,写成函数就是:
\( h_\theta(x_1,x_2)={\theta_0}+{\theta_1}{x_1}+{\theta_2}{x_2} \)
其中\(x_1\)是房子面积,\(x_2\)是房间数,\(h\)是对应的房子面积,\(\theta_j\)就是我们需要求的系数。
对于每个具体问题,需要根据测量数据的情况来确定是否为线性。这里假设为线性模型会限制适用范围,如果房屋面积与价格不是线性关系,则此模型估计的房子价格可能会偏差很大。因此实际上这里也可以假设为其他关系(如指数、对数等),那么估计结果可能就极度不准确了,当然那也就不是线性回归,这里就不必讨论。具体为什么选择线性模型,将在后面广义回归模型中来解答。
上面公式写成向量形式,则为
\( h_\theta(x)=\sum_{i=0}^n{\theta_i{x_i}}=\theta^T{x} \)
其中
\(\theta=(\theta_0, \theta_1,..., \theta_n)^T\)
\( x=(1,x_1, ... ,x_n)^T \)
那么上面的测量数据可以表示为\( (x^{(1)},y^{(1)}), (x^{(2)},y^{(2)}),..., (x^{(m)},y^{(m)}) \),其中的y为测量的房屋面积。这样如何根据这m个测量数据来求解参数\(\theta \)就是我们需要解决的问题了。
我们可以通过保证此组测量的预测误差最小来约束求解。代价函数为
\(J(\theta)={\frac{1}{2}}\sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})^2}\)
该代价函数表达的是测量数据的均方误差和。通过最小化该代价函数,即可估计出参数\( \theta \)。前面那个1/2并没有实质意义,主要为了后面求导方便加的;实际上为1/m更具有绝对意义。
回归算法求解
如何求解上述问题?主要有梯度下降法,牛顿迭代法,最小二乘法。这里主要讲梯度下降法,因为该方法在后面使用较多,如神经网络、增强学习等求解都是使用梯度下降。
函数在沿着其梯度方向增加最快的,那么要找到该函数的最小值,可以沿着梯度的反方向来迭代寻找。也就是说,给定一个初始位置后,寻找当前位置函数减小最快的方向,加上一定步长即可到达下一位置,然后再寻找下一位置最快的方向来到达再下一个位置……,直至其收敛。上述过程用公式表达出来即如下所示:
\( \theta_j = \theta_j - \alpha{\frac{\partial}{\partial{\theta_j}}}{J(\theta)}\)
根据上述表达式,可以求得代价函数的偏导数为:
\( {\frac{\partial}{\partial{\theta_j}}}{J(\theta)} = \sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)}) {\frac{\partial}{\partial{\theta_j}}}{h_\theta(x^{(i)})}} = \sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}} \)
这样,迭代规则为
\( \theta_j = \theta_j - \alpha\sum_{i=1}^m{(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}}\quad (j=1,2,...,n)\)
这个公式即是所谓的批量梯度下降。仔细观察该公式,每次迭代都需要把m个样本全部计算一遍,如果m很大时,其迭代将非常慢,因此一种每次迭代只计算1个样本的随机梯度下降(或增量梯度下降)可以极大减少运算量,其迭代如下:
\( \theta_j = \theta_j - \alpha {(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}}\quad (i=1,2,...,n \quad j=1,2,...,n)\)
若所有样本迭代完成后还未收敛,则继续从第1个样本开始迭代。
算法实现与结果
首先使用下面代码生成一组数据,为了后续显示方便,数据为一条直线上叠加一定噪声:
1 N = 100; 2 x = rand(N, 1) * 10; 3 y = 5 * x + 10 + 5 * randn(N, 1); 4 Sample = [x y]; 5 save('data.mat', 'Sample') 6 figure,plot(x, y, 'o');