斯坦福大学《Machine Learning》第10周学习笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/junjun150013652/article/details/80902536

Large Scale Machine Learning大规模机器学习


Gradient Descent with Large Datasets具有大数据集的梯度下降

Learning With Large Datasets学习大型数据集

我们已经知道 得到一个高效的机器学习系统的最好的方式之一是 用一个低偏差的学习算法 然后用很多数据来训练它 

但训练大的数据集也有它自己的问题 特别是计算量的问题 假设我们的训练集的大小m是100,000,000 假设我们要训练一个线性回归模型 或者是逻辑回归模型 这是梯度下降的规则 

当m是一个亿的时候 你需要加一亿个项 来计算这些导数项和计算一步的梯度下降 用求一亿个项目总和的计算量 来计算仅仅一步的梯度下降 

后面会讲到 把这个算法换掉的或者是找一个效率更高的算法来算这个导数 

当然 在我们训练一个上亿条数据的模型之前 我们还应该作为一个很好的检查是去看看用一千个数据是否合适 来检查小一些的数据集是不是好用 通常的方法是画学习曲线 如果你画了学习曲线而且你的训练目标看上去像左边这样  这看起来像高方差的学习算法 我们会对增加训练集的大小来提高性能更有信心 

而相比之下如果你画的学习曲线是右边这样的  这看起来像经典的高偏差学习算法 那么增加m不是个好办法 你应该多加一些特征 或者在你的神经网络里加一些隐藏的单元等等 所以最后你会变成一个像左边的图 

后面 我们会看到两个主要的想法 第一个叫做随机的梯度下降 第二个叫做映射化简 来处理大数据集

Stochastic Gradient Descent随机梯度下降

对于很多机器学习算法 包括线性回归、逻辑回归、神经网络等等 算法的实现都是通过得出某个代价函数 或者某个最优化的目标来实现的 然后使用梯度下降这样的方法来求得代价函数的最小值 当我们的训练集较大时 梯度下降算法则显得计算量非常大 

下面介绍一种跟普通梯度下降不同的方法 随机梯度下降(stochastic gradient descent) 用这种方法我们可以将算法运用到较大训练集的情况中 

下面是使用梯度下降法来训练某个线性回归模型 

在内层循环中 你需要用这个式子反复更新参数θ的值 多步迭代最终会将参数锁定到全局最小值 迭代的轨迹看起来非常快地收敛到全局最小

下面我们依然以线性回归为例 但随机梯度下降的思想也可以应用于其他的学习算法 比如逻辑回归、神经网络或者其他依靠梯度下降来进行训练的算法中 

梯度下降法的问题是 当m值很大时 如美国有3亿人口 计算这个微分项的计算量就变得很大 因为需要对所有m个训练样本求和 这种梯度下降算法也被称为批量梯度下降(batch gradient descent) “批量”就表示我们需要每次都考虑所有的训练样本  如果你真的有这3亿人口的数据存在硬盘里 那么这种算法就需要把所有这3亿人口数据读入计算机 仅仅就为了算一个微分项而已 你需要将这些数据连续传入计算机 因为计算机存不下那么大的数据量 所以你需要很慢地读取数据 然后计算一个求和 再来算出微分 所有这些做完以后 你才完成了一次梯度下降的迭代 最后 要让算法收敛 绝对需要花很长的时间

而随机梯度下降  在每一步迭代中 不用考虑全部的训练样本 只需要考虑一个训练样本 如图所示 它的 代价函数的定义有一点区别 

随机梯度下降法的第一步是 将所有m个训练样本重新排列  在i等于1到m中进行循环 也就是对所有m个训练样本进行遍历 然后进行如上更新 实际上就是扫描所有的训练样本 首先是我的第一组训练样本(x(1),y(1)) 然后只对这第一个训练样本 对它的代价函数 计算一小步的梯度下降 换句话说 我们要关注第一个样本 然后把参数θ稍微修改一点 使其对第一个训练样本的拟合变得好一点 完成这个内层循环以后 再转向第二个训练样本 以此类推 直到完成所有的训练集 然后外部这个重复循环会多次遍历整个训练集 跟批量梯度下降不同 随机梯度下降不需要等到对所有m个训练样本 求和来得到梯度项 而是只需要对单个训练样本求出这个梯度项 

批量梯度下降更新参数θ的收敛过程 会倾向于一条近似的直线 一直找到全局最小值 

随机梯度下降中 每一次迭代都会更快 每一次迭代只需要保证对一个训练样本拟合好就行了 所以看起来它是以某个比较随机、迂回的路径在朝全局最小值逼近 实际上随机梯度下降是在某个靠近全局最小值的区域内徘徊 而不是直接逼近全局最小值并停留在那点 所以 通常我们用随机梯度下降法 也能得到一个很接近全局最小值的参数 

外层循环应该执行多少次呢 这取决于训练样本的大小 通常一次就够了 最多到10次 是比较典型的 

Mini-Batch Gradient Descent小批量梯度下降

小批量梯度下降算法  有时候甚至比随机梯度下降还要快一点 

首先来总结一下我们已经讨论过的算法 在批量梯度下降中每次迭代我们都要用所有的m个样本 然而在随机梯度下降中每次迭代我们只用一个样本 小批量梯度下降做的介于它们之间 准确地说 在这种方法中我们每次迭代使用b个样本 b是一个叫做"小批量规模"的参数 所以这种算法介于随机梯度下降和批量梯度下降之间 b的一个标准的取值可能是2到100之间的任何一个数  

具体来说 小批量梯度下降可能比随机梯度下降好 仅当你有好的向量化实现时 小批量梯度下降的一个缺点是有一个额外的参数b 你需要调试小批量大小 因此会需要一些时间 但是如果你有一个好的向量化实现这种方法有时甚至比随机梯度下降更快 

Stochastic Gradient Descent Convergence随机梯度下降收敛

运行随机梯度下降算法时 你如何确保调试过程已经完成 并且能正常收敛呢? 以及如何调整随机梯度下降中学习速率α的值 ?

我们确定批量梯度下降已经收敛的一个标准方法 是画出最优化的代价函数 关于迭代次数的变化 

为了检查随机梯度下降的收敛性 我们要做的是 每1000次迭代运算中 我们对最后1000个样本的cost值求平均然后画出来 通过观察这些画出来的图 我们就能检查出随机梯度下降是否在收敛 这是几幅画出来的图的例子 

第一幅图:假如你已经画出了最后1000组样本的cost函数的平均值 由于它们都只是1000组样本的平均值 因此它们看起来有一点嘈杂 因此cost的值不会在每一个迭代中都下降 如果你得到像这样的图 那么你应该判断这个算法是在下降的  然后从蓝色箭头的点开始变得平缓 说明你的学习算法已经收敛了 如果你想试试更小的学习速率(红色曲线) 那么你很有可能看到的是 算法的学习变得更慢了 代价函数的下降也变慢了 但是很有可能会让算法收敛到一个好一点的解 注意 随机梯度下降不是直接收敛到全局最小值 而是在局部最小附近反复振荡 所以使用一个更小的学习速率 最终的振荡就会更小 

第二幅图:如果你把这个数 1000 提高到5000组样本 那么可能你会得到一条更平滑的曲线 增大平均的训练样本数的缺点就是 现在每5000个样本才能得到一个数据点 因此你所得到的关于学习算法表现的反馈 就显得有一些“延迟” 因为每5000个样本才能得到图上的一个数据点 而不是每1000个样本就能得到

第三幅图:算法没有很好地学习  代价项并没有下降 但同样地 如果你对这种情况时 也用更大量的样本进行平均 你很可能会观察到红线所示的情况 能看得出 实际上代价函数是在下降的 只不过蓝线用来平均的样本数量太小了 并且蓝线太嘈杂 你看不出来代价函数的趋势确实是下降的 所以可能用5000组样本来平均 比用1000组样本来平均 更能看出趋势 当然 即使是使用一个较大的样本数量 比如我们用5000个样本来平均 我用另一种颜色来表示 即使如此 你还是可能会发现 这条学习曲线是这样的 它还是比较平坦 即使你用更多的训练样本 如果是这样的话 那可能就更肯定地说明 不知道出于什么原因 算法确实没怎么学习好  那么你就需要调整学习速率 或者改变特征变量 或者改变其他的什么 

第四幅图:这是一个很明显的信号 告诉你算法正在发散 那么你要做的事 就是用一个更小一点的学习速率α 

当运行随机梯度下降时 算法会从某个点开始 然后曲折地逼近最小值 但它不会真的收敛 而是一直在最小值附近徘徊 因此你最终得到的参数 实际上只是接近全局最小值 而不是真正的全局最小值 (学习速率α保持不变)

如果你想让随机梯度下降确实收敛到全局最小值 你可以随时间的变化减小学习速率α的值 

以上是一种典型的方法来设置α的值 但是这里增加了两个额外的参数 需要你花时间来确定常数1和常数2上 这让算法显得更繁琐 因此我们很少采用逐渐减小α的值的方法 在随机梯度下降中 你看到更多的还是让α的值为常数 虽然两种做法的人都有 

Advanced Topics

Online Learning在线学习

下面讨论一种新的大规模的 机器学习机制 叫做 在线学习机制 

假定你有一个提供运输服务的公司 同时假定你有一个网站 让用户们可多次登陆  然后他们告诉你  他们想从哪里寄出包裹 以及 包裹要寄到哪里去  然后你的网站开出运输包裹的 的服务价格 比如 我会收取$50来运输你的包裹 我会收取$20之类的 

然后根据 你开给用户的这个价格 用户接受这个运输服务 那么这就是个正样本 有时他们会拒绝 我们假定我们想要一个 学习算法来帮助我们 优化我们想给用户 开出的价格 

我们想要做的就是 学习 在给出的价格下他们将会 选择 运输包裹的几率 

运行算法如上  当有用户访问网站的时候  我们会得到一个(x,y)对  在线学习算法 要做的就是 利用刚得到的(x,y)数据对来更新θ  然后我们丢弃这个样本 当然 如果我们只有 少量的用户 那么我们就不选择像这样的在线学习算法 你可能最好是要 保存好所有的 数据 保存在一个固定的 数据集里 然后对这个数据集使用某种算法 

这种在线学习算法 会带来的有趣的效果 那就是 它可以对正在变化的用户偏好进行调适 而且特别的 如果 随着时间变化 因为 大的经济环境发生变化 用户们可能会 开始变得对价格更敏感 然后愿意支付 又或者各种因素 变得对用户的影响更大了 如果你开始拥有 某一种新的类型的用户涌入你的网站 这样的在线学习算法 也可以根据变化着的 用户偏好进行调适 

举个例子说 你有一个在线 卖电话的商铺 一个卖移动电话或者手机的商铺 而且你有一个用户界面 可以让用户登陆你的网站 并且键入一个 搜索条目 例如“安卓 手机 1080p 摄像头” 那么这些搜索字符可以构建一个 特征矢量x 然后我们通过用户的点击率来 给相应的用户展示他们最有可能点击的10部手机 对于 这10部手机中的每一个 我们又会得到 一个特征矢量x 和 y的取值 我们也会观察这些取值 这样 运行此类网站的 一种方法就是 连续给用户展示 你的十个最佳猜测 

所以 这就是在线学习机制  然后就像我们所看到的 我们所使用的这个算法 与随机梯度下降算法 非常类似 唯一的区别的是 我们不会 使用一个固定的数据集 我们会做的是获取 一个用户样本 从那个样本中学习 然后 丢弃那个样本并继续下去 而且如果你对某一种应用有一个连续的 数据流 这样的算法可能会 非常值得考虑 当然 在线学习的一个优点 就是 如果你有一个变化的 用户群 又或者 你在尝试预测的事情 在缓慢变化 就像你的用户的 品味在缓慢变化 这个在线学习 算法可以慢慢地 调试你所学习到的假设 将其调节更新到最新的 用户行为 

Map Reduce and Data Parallelism

之前提到的这些算法 都只能在一台计算机上运行 但是 有些机器学习问题 太大以至于不可能 只在一台计算机上运行 下面介绍进行大规模机器学习的另一种方法 称为映射约减 (map reduce) 方法

假设我们要 拟合一个线性回归模型 或者逻辑回归模型 或者其他的什么模型 让我们再次从随机梯度下降算法开始吧 这就是我们的随机梯度下降学习算法  我们将假定m固定为400个样本 

根据映射化简的思想 一种解决方案是 将训练集划分成几个不同的子集 我假定我有 4台计算机 它们并行的 处理我的训练数据 如图所示最后 当这些计算机 全都完成了各自的工作 我会将这些临时变量 送到一个 中心计算服务器 这台服务器会 将这些临时变量合并起来 根据右边的公式 来更新参数θj 

其实 这个公式计算的数值 和原先的梯度下降公式计算的数值 是完全一样的

总结来说 映射约减技术是这么工作的 我们有一些训练样本 如果我们希望使用4台计算机 并行的运行机器学习算法 那么我们将训练样本等分 尽量均匀地分成4份 然后 我们将这4个 训练样本的子集送给4台不同的计算机 每一台计算机 对四分之一的 训练数据 进行求和运算 最后 这4个求和结果 被送到一台中心计算服务器 负责对结果进行汇总 特别的 如果没有网络延时 也不考虑 通过网络来回传输数据 所消耗的时间 那么你可能可以得到4倍的加速 

如果你打算 将映射化简技术用于 加速某个机器学习算法 也就是说 你打算运用多台不同的计算机 并行的进行计算 那么你需要问自己一个很关键的问题 那就是 你的机器学习算法 是否可以表示为训练样本的某种求和 

因此 更广义的来说 通过将机器学习算法 表示为 求和的形式 或者是 训练数据的函数求和形式 你就可以运用映射化简技术 来将算法并行化 这样就可以处理大规模数据了 

最后再提醒一点 目前我们只讨论了 运用映射化简技术 在多台计算机上 实现并行计算 也许是一个计算机集群 也许是一个数据中心中的多台计算机  但实际上 我们也可以将这种技术应用到一台计算机的多核上面  他的一个优势 是你不必担心网络延时问题 

条件是你有一台 多核计算机 并且使用了某个线性代数函数库 某些线性代数函数库 会自动利用多个核 并行地完成线性代数运算 

参考资料

https://www.coursera.org/learn/machine-learning/

猜你喜欢

转载自blog.csdn.net/junjun150013652/article/details/80902536