机器学习:回归 梯度下降法

来源:互联网 发布:软件企业简介 编辑:程序博客网 时间:2024/03/28 20:26

回归在数学上来说是给定一个点集,能够用一条曲线去拟合之,如果这个曲线是一条直线,那就被称为线性回归,如果曲线是一条二次曲线,就被称为二次回归,回归还有很多的变种,如locally weighted回归,logistic回归,等等,这个将在后面去讲。

   用一个很简单的例子来说明回归,这个例子来自很多的地方,也在很多的open source的软件中看到,比如说weka。大概就是,做一个房屋价值的评估系统,一个房屋的价值来自很多地方,比如说面积、房间的数量(几室几厅)、地段、朝向等等,这些影响房屋价值的变量被称为特征(feature),feature在机器学习中是一个很重要的概念,有很多的论文专门探讨这个东西。在此处,为了简单,假设我们的房屋就是一个变量影响的,就是房屋的面积。

   假设有一个房屋销售的数据如下:

   面积(m^2)  销售价钱(万元)

   123            250

   150            320

   87              160

   102            220

   …               …

   这个表类似于帝都5环左右的房屋价钱,我们可以做出一个图,x轴是房屋的面积。y轴是房屋的售价,如下:

   image

   如果来了一个新的面积,假设在销售价钱的记录中没有的,我们怎么办呢?

   我们可以用一条曲线去尽量准的拟合这些数据,然后如果有新的输入过来,我们可以在将曲线上这个点对应的值返回。如果用一条直线去拟合,可能是下面的样子:

    image

   绿色的点就是我们想要预测的点。

   首先给出一些概念和常用的符号,在不同的机器学习书籍中可能有一定的差别。

   房屋销售记录表 - 训练集(training set)或者训练数据(training data), 是我们流程中的输入数据,一般称为x

   房屋销售价钱 - 输出数据,一般称为y

   拟合的函数(或者称为假设或者模型),一般写做 y = h(x)

   训练数据的条目数(#training set), 一条训练数据是由一对输入数据和输出数据组成的

   输入数据的维度(特征的个数,#features),n

   下面是一个典型的机器学习的过程,首先给出一个输入数据,我们的算法会通过一系列的过程得到一个估计的函数,这个函数有能力对没有见过的新数据给出一个新的估计,也被称为构建一个模型。就如同上面的线性回归函数。

 

   image

    我们用X1,X2..Xn 去描述feature里面的分量,比如x1=房间的面积,x2=房间的朝向,等等,我们可以做出一个估计函数:

image

    θ在这儿称为参数,在这儿的意思是调整feature中每个分量的影响力,就是到底是房屋的面积更重要还是房屋的地段更重要。为了如果我们令X0 = 1,就可以用向量的方式来表示了:

image

    我们程序也需要一个机制去评估我们θ是否比较好,所以说需要对我们做出的h函数进行评估,一般这个函数称为损失函数(loss function)或者错误函数(error function),描述h函数不好的程度,在下面,我们称这个函数为J函数

   在这儿我们可以做出下面的一个错误函数:

image 

    这个错误估计函数是去对x(i)的估计值与真实值y(i)差的平方和作为错误估计函数,前面乘上的1/2是为了在求导的时候,这个系数就不见了。

    如何调整θ以使得J(θ)取得最小值有很多方法,其中有最小二乘法(min square),是一种完全是数学描述的方法,在stanford机器学习开放课最后的部分会推导最小二乘法的公式的来源,这个来很多的机器学习和数学书上都可以找到,这里就不提最小二乘法,而谈谈梯度下降法。


梯度下降


 这几天在看《统计学习方法》这本书,发现 梯度下降法 在 感知机 等机器学习算法中有很重要的应用,所以就特别查了些资料。   

 

   一.介绍

      梯度下降法(gradient descent)是求解无约束最优化问题的一种常用方法,有实现简单的优点。梯度下降法是迭代算法,每一步需要求解目标函数的梯度向量。

 

   二.应用场景

     1.给定许多组数据(xi, yi),x(向量)为输入,yi为输出。设计一个线性函数y=h(x)去拟合这些数据。

     2.感知机:感知机(perceptron)为二类分类的线性分类模型。 输入为实例的特征向量,输出为实例的类别, 取+1 和 -1 二值。

 

     下面分别对这两种应用场景进行分析。

     1.对于第一种场景:

        既然是线性函数,在此不妨设为 h(x) = w0*x0 + w1*x1。

        此时我们遇到的问题就是如何确定w0和w1这两个参数,即w=(w0,w1)这个向量。

        既然是拟合,则拟合效果可以用平方损失函数:E(w)=∑ [ h(x)- y ] ^2 / 2 来衡量。

        其中w是权重二维向量,x是输入二维向量,x和y都是训练集的数据,即已知。

        至于后面除于2只是为了之后的推导过程中对E求导时候可以消除系数,暂时可以不管。

        因此该问题变成了求E(w)最小值的无约束最优化问题

      2.对于第二种场景:

        假设输入空间(特征向量)为x,输出空间为y = {+1, -1},由输入空间到输出空间的如下函数

                        f(x) = sign(w · x + b)       w∈Rn     其中 w 叫做权值或者权值向量, b叫做偏振。w · x 表示向量w和x的点积

         感知机sign(w · x + b)的损失函数为  L(w, b) = -∑yi(w · xi + b)              x ∈M, M为误分类点集合。

        因此该问题变成了求L(w, b)最小值的无约束最优化问题

 

   三.梯度下降方法

       梯度其实就是高数求导方法,对E这个公式针对每个维数(w0,w1)求偏导后的向量▽E(w)=(∂E/∂w0,∂E/∂w1)

       1. 对于第一种场景

          对E这个公式针对每个维数(w0,w1)求偏导后的向量▽E(w)=(∂E/∂w0,∂E/∂w1)

          梯度为最陡峭上升的方向,对应的梯度下降的训练法则为: w=w-η▽E(w)     这里的η代表学习速率,决定梯度下降搜索中的步长 。

          上式的w是向量,即可用将该式写成分量形式为:wi=wi-η*∂E/∂wi

          现在关键就使计算∂E/∂wi:

          推导过程很简单,书上写的很详细,这里只记录结论(其实就是对目标函数求导):

          ∂E/∂wi=∑(h(x)-y)*(xi)

          这里的∑是对样本空间,即训练集进行一次遍历,耗费时间较大,可以使用梯度下降的随机近似:

       2. 对于第二种场景

           感知机学习算法是误分类驱动的,具体采用随机梯度下降方法

           ▽wL(w, b) =   -∑yixi       

           ▽bL(w, b) =   -∑yi

           随机选取一个误分类点(xi,   yi), 对w, b进行更新:

            w  <——   w - η * (-yixi)

            b  <——    b - η * (-yi)               式中η(0 < η <= 1)是步长,在统计学习中又称为学习率(learning rate)

  

   四.随机梯度下降的随机近似:

      既然是随机近似,则顾名思义,肯定是用近似方法来改善梯度下降时候的时间复杂度问题。

      正如上所说,在∂E/∂wi=∑(h(x)-y)*(xi) 的时候∑耗费了大量的时间,特别是在训练集庞大的时候。

      所以肯定有人会猜想,如果把求和去掉如何,即变为∂E/∂wi=(h(x)-y)*(xi)。

      幸运的是,猜想成立了。

      只是要注意一下标准的梯度下降和随机梯度下降的区别:

    1.标准下降时在权值更新前汇总所有样例得到的标准梯度,随机下降则是通过考察每次训练实例来更新。

    2.对于步长 η的取值,标准梯度下降的η比随机梯度下降的大。

    因为标准梯度下降的是使用准确的梯度,理直气壮地走,随机梯度下降使用的是近似的梯度,就得小心翼翼地走,怕一不小心误入歧途南辕北辙了。

    3.当E(w)有多个局部极小值时,随机梯度反而更可能避免进入局部极小值中。

 四.代码及实例:

  1. 对于第一种场景

#coding=utf-8import copy#   * 随机梯度下降实验:#   * 训练集输入为矩阵:#   * 1,4#   * 2,5#   * 5,1#   * 4,2#   * 输出结果为:#   * 19#   * 26#   * 19#   * 20#   * 需要参数为 w:#   * 目标函数:y=w0*x0+w1*x1;if __name__ == '__main__':    matrix=[]    result=[]    w=[]    x=[1,4]    matrix.append(copy.deepcopy(x))    x=[2,5]    matrix.append(copy.deepcopy(x))    x=[5,1]    matrix.append(copy.deepcopy(x))    x=[4,2]    matrix.append(copy.deepcopy(x))        result=[19,26,19,20];        w=[0,0];#初始为零向量    loss=10.0;    n = 0.01;        #步长     i=0    while i<100 and loss>0.001:         error_sum=0;         j=i%4;            h=0         for  k in range(0,2):            h+=matrix[j][k]*w[k];                 error_sum = h - result[j];         k=0         for k in range(0,2):            w[k]-= n * (error_sum) * matrix[j][k];#//这里是关键         print w[0],w[1]         loss=0;         for j in range(0,4):            sum=0;            for k in range(0,2):                 sum += matrix[j][k] * w[k];            loss += (sum - result[j]) * (sum-result[j]);         print(loss)         i+=1

结果可以得出  w0=3,w1=4。
 1. 对于第二种场景
#coding=utf-8import copy#   * 随机梯度下降实验:#   * 训练集输入为矩阵:#   * 1,4#   * 2,5#   * 5,1#   * 4,2#   * 输出结果为:#   * 19#   * 26#   * 19#   * 20#   * 需要参数为 w:#   * 目标函数:y=w0*x0+w1*x1;if __name__ == '__main__':    x=[]    a=[3,3]    x.append(copy.deepcopy(a))    a=[4,3]    x.append(copy.deepcopy(a))    a=[1,1]    x.append(copy.deepcopy(a))    y=[1, 1, -1];    w=[0,0];#初始为零向量    b = 0;    n = 1;        #步长       while(1):         for j in range(0,4):            if j==3:                 break            if y[j] * (w[0] * x[j][0] + w[1] * x[j][1] + b) <= 0:                 break                   if(j < 3):             for k in range(0,2):                 w[k] += n * y[j] * x[j][k];#这里是关键             b += n * y[j];         else:             break         print j, w[0], w[1], b


 结果可以得出  w0=1,w1=1, b = -3 。

参考:

1.    http://blog.csdn.net/wuyanyi/article/details/8003946 

2.    李航 统计学习方法



随机梯度下降法




一、误差准则函数与随机梯度下降:

数学一点将就是,对于给定的一个点集(X,Y),找到一条曲线或者曲面,对其进行拟合之。同时称X中的变量为特征(Feature),Y值为预测值。

如图:


一个典型的机器学习的过程,首先给出一组输入数据X,我们的算法会通过一系列的过程得到一个估计的函数,这个函数有能力对没有见过的新数据给出一个新的估计Y,也被称为构建一个模型。

我们用X1、X2...Xn 去描述feature里面的分量,用Y来描述我们的估计,得到一下模型:


我们需要一种机制去评价这个模型对数据的描述到底够不够准确,而采集的数据x、y通常来说是存在误差的(多数情况下误差服从高斯分布),于是,自然的,引入误差函数:


关键的一点是如何调整theta值,使误差函数J最小化。J函数构成一个曲面或者曲线,我们的目的是找到该曲面的最低点:


假设随机站在该曲面的一点,要以最快的速度到达最低点,我们当然会沿着坡度最大的方向往下走(梯度的反方向)

用数学描述就是一个求偏导数的过程:



这样,参数theta的更新过程描述为以下:

   (α表示算法的学习速率)

    一个很重要的地方值得注意的是,梯度是有方向的,对于一个向量θ,每一维分量θi都可以求出一个梯度的方向,我们就可以找到一个整体的方向,在变化的时候,我们就朝着下降最多的方向进行变化就可以达到一个最小点,不管它是局部的还是全局的。

    用更简单的数学语言进行描述步骤2)是这样的:

  image    倒三角形表示梯度,按这种方式来表示,θi就不见了,看看用好向量和矩阵,真的会大大的简化数学的描述啊

二、算法实现与测试:

通过一组数据拟合 y = theta1*x1 +theta2*x2

[python] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #Python 3.3.5  
  2. # matrix_A  训练集  
  3. matrix_A = [[1,4], [2,5], [5,1], [4,2]]  
  4. Matrix_y = [19,26,19,20]  
  5. theta = [2,5]  
  6. #学习速率  
  7. leraing_rate = 0.005  
  8. loss = 50  
  9. iters = 1  
  10. Eps = 0.0001  
  11. while loss>Eps and iters <1000 :  
  12.     loss = 0  
  13.     for i in range(3) :  
  14.         h = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1]   
  15.         theta[0] = theta[0] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][0]  
  16.         theta[1] = theta[1] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][1]  
  17.     for i in range(3) :  
  18.         Error = 0  
  19.         Error = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] - Matrix_y[i]  
  20.         Error = Error*Error  
  21.         loss = loss +Error  
  22.     iters = iters +1  
  23. print ('theta=',theta)  
  24. print ('iters=',iters)  
求解结果:
[python] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. >>>   
  2. theta= [2.99809592161579454.001522800837675]  
  3. iters= 75  
但如果对输入数据添加一些噪声

[python] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. matrix_A = [[1.05,4], [2.1,5], [5,1], [4,2]]  
求解结果为:

[python] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. >>>   
  2. theta= [3.00959506851977253.944718521027671]  
  3. iters= 1000  
可见在有噪声的情况下,要及时调整模型误差精度、迭代次数上限,一期达到我们的需求。
0 0
原创粉丝点击