机器学习笔记(八)——随机梯度上升(降低)算法调优

前言概述

上一篇文章对逻辑回归的原理和基本思想作了一些简要介绍,并经过引入Sigmoid函数和梯度公式成功推导出了梯度上升和梯度降低公式,上文分类实例是依据全批量提高上升法,而本文会介绍全批量梯度上升的一种优化算法——随机梯度上升,若是还未懂得逻辑回归和推理公式原理,还请观看上一篇文章:机器学习笔记(七)——初识逻辑回归、两种方法推导梯度公式。python

随机梯度上升

区别对比

在讲解全批量梯度上升和随机梯度上升的区别以前,先看一下两者的公式之间的对比,有助于以后的理解。算法

全批量梯度上升法:segmentfault

随机梯度上升法:数组

全批量梯度上升公式咱们已经很熟悉了,上一篇文章有介绍;其实随机梯度上升与全批量的公式十分类似,原理也是大体相同的,不一样点体如今何处呢?全批量在每次更新回归系数时都须要遍历整个数据集,这种方法在处理小数据集时尚可,但若是有数十亿样本和成千上万的特征,那么该方法的计算复杂度过高。而随机梯度上升是一次仅用一个样本点来更新回归系数,这样作大大减少了计算复杂度,而且提升了函数的收敛速度。dom

更改算法

随机梯度上升算法伪代码以下机器学习

全部回归系数初始化为1
对数据集中每一个样本
      计算该样本的梯度
      使用alpha*gradient更新回归系数值
返回回归系数值

由于两个公式大致上一致,因此随机梯度上升法的代码只会稍微有些出入。函数

def stocGradAscent1(dataMatrix, classLabels):
    #将列表转化为array格式
    dataMatrix = np.array(dataMatrix)
    # 获取dataMatrix的行、列数
    m,n = np.shape(dataMatrix)
    # 初始化回归系数和步长
    weights = np.ones(n)
    alpha = 0.01
    for i in range(m):
        # 遍历样本,每次选出一个,计算h
        h = sigmoid(sum(dataMatrix[i]*weights))
        # 计算偏差
        error = classLabels[i] - h
        # 更新回归系数
        weights = weights + alpha * error * dataMatrix[i]
    return weights

能够看到两种算法有些区别:第一,随机梯度上升的变量h和偏差error都是数值,而全批量中两者都是向量格式;第二,随机梯度没有矩阵运算,全部变量的数据类型都为Numpy数组。学习

执行上述代码能够获得一条新的最佳拟合直线图,以下:优化

能够看到,这条新的最佳拟合直线只分对了二分之一的样本。明明是对算法进行调优,但是准确率怎么越调越低呢?spa

缘由是全批量梯度上升法是在整个数据集上迭代了500次才获得的,迭代次数要远大于随机梯度方法,而判断一个算法优劣的可靠方法是看它是否收敛,也就是参数是否达到了稳定值,是否还会不断变化。

下图为两种方法迭代次数与回归系数之间的关系:

能够看到全批量梯度三个回归图像与随机梯度相比波动幅度都比较大,用最明显的回归系数X2做比较,前者在下标为300时收敛完成,然后者在下标14000时曲线才近乎平稳;但这里须要注意的是,全批量梯度每次迭代都是利用整个数据集,因此该方法收敛完成时的准确迭代次数应该是30000次,比随机梯度的迭代次数要多的多。

随机梯度方法在大的波动以后,还有不少小的周期波动,产生这种现象的缘由是存在一些不能正确分类的样本点,在每次迭代时会引起系数的剧烈改变。咱们但愿算法能够避免波动问题,从而收敛到某个值,而且加快收敛速度。

算法调优

因此对随机梯度上升算法作如下改进:

def stocGradAscent2(dataMatrix, classLabels, numIter=150):
    #将列表转化为array格式
    dataMatrix = np.array(dataMatrix)
    # 获取dataMatrix的行、列数
    m,n = np.shape(dataMatrix)
    # 初始化回归系数和步长
    weights = np.ones(n)
    for j in range(numIter):
        dataIndex = list(range(m))
        for i in range(m):
            # 逐渐减少alpha,每次减少量为1.0/(j+i)
            一、alpha = 4/(1.0+j+i)+0.01
            # 随机选取样本
            二、randIndex = int(random.uniform(0,len(dataIndex)))
            # 随机选取的一个样本,计算h
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            # 计算偏差
            error = classLabels[randIndex] - h
            # 更新回归系数
            weights = weights + alpha * error * dataMatrix[randIndex]
            # 删除已经使用过的样本
            del(dataIndex[randIndex])
    return weights

第一处改进目的在于每一次迭代都会调整步长alpha的值,alpha每次迭代都会减少1/(j+i),其中j是迭代次数,i是样本点的下标。虽然alpha会随着迭代次数不断减少,但永远不会减少到0,其中还存在一个常数项,这是由于在屡次迭代以后alpha的值近乎为0,这样新数据对于回归系数的更新几乎没有做用。

这里再利用图片再讲解一下为何要这样优化alpha。

上图是一个二次函数的图像,在最开始时梯度较大,步长alpha能够比较大,但梯度是呈现逐渐减少趋势的,这时离最优值也愈来愈近,步长alpha也要随之减少。若是降低速率很大,在接近最优势时,梯度乘以了一个数值比较大的alpha,就会出现下图这类状况。

例如从点1直接跳到了点2,开始震荡,上述迭代次数与回归系数关系图中的较大震荡产生的缘由,而上述对步长alpha的优化便可避免这类状况,虽然举例用的是梯度降低,但梯度上升和梯度降低的原理是一致的。

第二处改进的目的是减小随机梯度关系图中周期性的波动,这里经过随机选取抽样样本更新回归系数,每次随机从列表中选取一个值,而后从列表中删掉该值,再进行下一次迭代,与决策树选取信息增益的方式相似。

下图给出了改进后的随机梯度上升法迭代次数与回归系数的关系图。

能够看出这种方法三个回归系数图像比固定步长alpha的方法收敛速度都要快,而且没有了周期性的波动,为了更直观地看到改进算法的效果,下图给出了利用改进后的算法绘制出的最佳拟合直线图。

最终随机梯度的分类效果与全批量梯度几乎同样,可是迭代次数却要少不少不少,因此前者很大程度上下降了算法的计算复杂度,减少了程序使用的内存。

总结

文末总结一下全批量梯度降低法、随机梯度降低法、小批量梯度降低法的优缺点即适应场合。

全批量梯度降低法(BGD):每次更新回归系数全部样本都参与。

  • 优势:分类准确,获取全局最优解
  • 缺点:当样本比较多时,训练速度特别慢
  • 适用场合:样本较少的数据集

随机梯度降低法(SGD):每次更新回归系数只有一个样本参与。

  • 优势:训练速度很快
  • 缺点:准确率会下降,并非朝着总体最优方向进行,容易获取到局部最优解
  • 适用场合:样本很是多的数据集

小批量梯度降低法(MBGD):每次更新回归系数有一部分样本参与。这种方法兼顾了上述两种方法的优势,同时也减弱了二者的缺点,算是两种前两种算法的一种平衡。若是数据集的样本数不是很极端,最好采用小批量梯度降低法。

关注公众号【奶糖猫】后台回复“随机梯度”可获取源码供参考,感谢阅读。
相关文章
相关标签/搜索