机器学习入门 6-5 梯度下降的向量化和数据标准化

2019-11-13 18:38:49 浏览数 (1)

本系列是《玩转机器学习教程》一个整理的视频笔记。本小节主要介绍梯度下降法的向量化,并引入对使用梯度下降法非常重要的数据归一化。

线性回归中梯度下降法的向量化

前几个小节实现梯度下降法的时候是通过for循环方式,前面也提到过for循环的方式效率低下,因此如果想要提高效率的话只需要将其转换成向量化的方式,借助Numpy模块的优势提高算法的效率。

此时在使用梯度下降法求解线性回归的时候,向量化处理主要集中在求梯度的过程,相对应的就是前面使用for循环一项一项的把梯度求出来的部分。

接下来,主要将上面的式子实现向量化,把他转换成矩阵运算的方式。首先看第0项和其他项不一样(第0项用于求解截距,其他项用于求解样本特征的系数),所以首先要做的就是对第0项和其余项进行统一。

接下来就是对在第0项添加X0的式子进行向量化的处理,其实前面实现梯度下降的时候已经实现了部分向量化,在求梯度的式子中每一个元素对应的式子看作是两个向量对应的点乘,在代码中使用"dot"的来实现。此时由于梯度中每一个元素都是点乘一个向量,那么将这些向量合在一起组成一个矩阵,就将上面求解梯度的式子转换成了矩阵的乘法,具体组合方式如下图所示:

接下来先将下图中右半部分的式子进行标号:

通常情况下向量会被表示成列向量的形式,但是如果两个矩阵能够相乘,需要满足第一个矩阵的列数等于第二个矩阵的行数,很明显如果"式子1"为列向量的话不能够进行矩阵乘法,因此如果进行矩阵乘法运算需要将"式子1"进行转置操作:

  1. "式子1"的shape = (1, m);
  2. “式子2”的shape = (m, n 1);
  3. "式子1".dot(“式子2”)的shape = (1, n 1)。

通过"式子1"与"式子2"点乘操作得到的结果的shape = (1, n 1),也就是"式子3",虽然在numpy中是不区分行向量和列向量的,因此通过"式子3"计算梯度也是可以的。本课程为了严谨起见,还是将梯度转换成相应的列向量,因此需要将"式子3"整体进行转置操作得到的结果就是"式子4"。

至此我们将求梯度的过程转换为向量化的方式,其实就是通过矩阵乘法计算梯度的"式子4":

接下来只需要在我们自己封装的LinearRegression类中将计算梯度的函数进行相应的修改即可。

接下来在jupyter中调用使用向量化方式计算梯度的梯度下降法:

梯度下降与数据归一化

通过前一小节的分析,知道了数据中各个特征的数据规模不同,可能会导致计算的梯度值非常大,虽然可以通过将eta步长值设置非常小来缓解这种问题,但是相应的就必须要增加迭达次数,而增加迭达次数显然会非常耗时。

总而言之,根源就是数据规模不同,其实前面在kNN算法中也提到过由于数据特征的量纲不同,导致计算数据点之间距离的时候,各个特征所贡献的距离权重不同,因此引入了数据归一化。同理,如果想要更好的解决梯度下降法中数据规模不同导致的收敛问题,同样可以使用数据归一化来处理。

前面介绍使用正规方程的方式求解线性回归的时候,并没有使用数据归一化操作,这是因为我们将线性回归模型的求解过程整体变成了一个公式的计算,在公式计算中牵扯的中间搜索的过程比较少,所以我们在使用正规方程求解的时候不需要使用数据归一化。而当我们使用梯度下降法的时候,事情就变的不一样的,由于梯度下降中有eta这个变量,首先会出现一个问题,如果最终这些数值不在一个维度上,将会影响梯度的结果,而梯度的结果乘上eta才是我们真正走的步长,此时这个步长就可能太大或者太小:

  1. 如果太大的话,导致结果不收敛;
  2. 如果太小的话,导致搜索过程太慢。

但是如果我们将所有的数据进行归一化,这个问题就完全的解决了。

接下来使用具体代码来实现数据归一化:

通过上面使用正规方程求解线性回归与使用梯度下降法求解线性回归所用时间对比发现,梯度下降法并没有显现出优势来,甚至比正规方程运行时间大的多。

上面创建了一些拥有1000个样本5000个特征的样本,可以看出此时的梯度下降法比正规方程法省了不少时间,当然增大数据量,效果更为明显。对于正规方程来说,对矩阵进行非常多的乘法运算,所以当矩阵维度比较大的时候,正规方法相应的耗时就会更高。

此时设置的样本数小于每个样本特征数,这是因为我们现在使用的梯度下降公式在计算梯度的时候,让每一个样本都来参与计算,这使得当样本量比较大的时候,计算梯度也相应的比较慢,但是有改进的方法,这就是下一小节要说的随机梯度下降法。

0 人点赞