Spark中的求解器,根据输入的训练数据及设定的迭代次数、正则化项、参数收敛精度等进行迭代求解模型的参数。Spark内部实现来两类求解器,基于随机梯度下降(miniBatch选取样本)的GradientDescent、基于大规模数值优化算法的LBFGS。

在整体架构上,两个类都继承自Optimizer,并需要调用Gradient和Updater

GradientDescent
GradientDescent是对随机梯度下降算法封装的一个求解器,通过runMiniBatchSGD方法实现模型参数的迭代计算,基本流程是:

1、根据miniBatchFraction参数进行样本抽样,获得一个小样本集

2、调用Gradient计算在小样本集上的梯度值

3、调用Updater,根据regParam、stepSize、numIterations等参数值更新模型参数

4、判断终止条件(精度收敛或者迭代次数达到上限),否则继续上面步骤。

核心代码如下;

while (!converged && i <= numIterations) {
  //将参数广播到各台机器上,实际上是集群下模型参数的共享和同步
  val bcWeights = data.context.broadcast(weights)
  // Sample a subset (fraction miniBatchFraction) of the total data
  // compute and sum up the subgradients on this subset (this is one map-reduce)
  //在各分区上调用seqOp计算梯度值、误差值
  //调用combOp对各分区计算的结果进行聚合
  //这样得到的是各分区计算得到的梯度值得总和,后面会利用miniBatchSize计算平均梯度并传入updater进行更新
  val (gradientSum, lossSum, miniBatchSize) = data.sample(false, miniBatchFraction, 42 + i)
    .treeAggregate((BDV.zeros[Double](n), 0.0, 0L))(
      seqOp = (c, v) => {
        // c: (grad, loss, count), v: (label, features)
        val l = gradient.compute(v._2, v._1, bcWeights.value, Vectors.fromBreeze(c._1))
        (c._1, c._2 + l, c._3 + 1)
      },
      combOp = (c1, c2) => {
        // c: (grad, loss, count)
        (c1._1 += c2._1, c1._2 + c2._2, c1._3 + c2._3)
      })
 
  if (miniBatchSize > 0) {
    /**
     * lossSum is computed using the weights from the previous iteration
     * and regVal is the regularization value computed in the previous iteration as well.
     */
    stochasticLossHistory += lossSum / miniBatchSize + regVal
    val update = updater.compute(
      weights, Vectors.fromBreeze(gradientSum / miniBatchSize.toDouble),
      stepSize, i, regParam)
    weights = update._1
    regVal = update._2
 
    previousWeights = currentWeights
    currentWeights = Some(weights)
    if (previousWeights != None && currentWeights != None) {
      converged = isConverged(previousWeights.get,
        currentWeights.get, convergenceTol)
    }
  } else {
    logWarning(s"Iteration ($i/$numIterations). The size of sampled batch is zero")
  }
  i += 1
}
LBFGS
梯度下降法是线性逼近的,在靠近最优点时容易出现震荡(即在最优点旁边晃来晃去,就是取不到这个最优值),相对来说,牛顿法、拟牛顿法、LM方法等二阶优化方法,由于非线性逼近的特性,收敛速度和收敛精度斗会高于梯度下降法,但这些方法都是相当消耗内存的,比如牛顿法,需要计算Hessian矩阵(二阶偏导数矩阵)及其逆矩阵 ,如果模型参数是N维,则Hessian矩阵大小为N*N,存储和计算逆矩阵斗相当困难,限制来在大规模机器学习中的应用。基于牛顿法和拟牛顿法,LBFGS在计算Hessian矩阵逆矩阵的时候做了一些近似工作。

LBFGS详细可参考http://mlworks.cn/posts/introduction-to-l-bfgs/

Spark本身没有实现LBFGS底层算法,而是调用来breeze包,Spark实现了损失函数CostFun,使用CachedDiffFunction类缓存最近的m次输入变量和梯度变量的差值。

private class CostFun(
  data: RDD[(Double, Vector)],
  gradient: Gradient,
  updater: Updater,
  regParam: Double,
  numExamples: Long) extends DiffFunction[BDV[Double]] {
 
  override def calculate(weights: BDV[Double]): (Double, BDV[Double]) = {
    // Have a local copy to avoid the serialization of CostFun object which is not serializable.
    val w = Vectors.fromBreeze(weights)
    val n = w.size
    val bcW = data.context.broadcast(w)
    val localGradient = gradient
    val (gradientSum, lossSum) = data.treeAggregate((Vectors.zeros(n), 0.0))(
        seqOp = (c, v) => (c, v) match { case ((grad, loss), (label, features)) =>
          val l = localGradient.compute(
            features, label, bcW.value, grad)
          (grad, loss + l)
        },
        combOp = (c1, c2) => (c1, c2) match { case ((grad1, loss1), (grad2, loss2)) =>
          axpy(1.0, grad2, grad1)
          (grad1, loss1 + loss2)
        })
    // broadcasted model is not needed anymore
    bcW.destroy()
    val regVal = updater.compute(w, Vectors.zeros(n), 0, 1, regParam)._2
    val loss = lossSum / numExamples + regVal
    val gradientTotal = w.copy
    axpy(-1.0, updater.compute(w, Vectors.zeros(n), 1, 1, regParam)._1, gradientTotal)
    axpy(1.0 / numExamples, gradientSum, gradientTotal)
    (loss, gradientTotal.asBreeze.asInstanceOf[BDV[Double]])
  }
}
def runLBFGS(
    data: RDD[(Double, Vector)],
    gradient: Gradient,
    updater: Updater,
    numCorrections: Int,
    convergenceTol: Double,
    maxNumIterations: Int,
    regParam: Double,
    initialWeights: Vector): (Vector, Array[Double]) = {
  val lossHistory = mutable.ArrayBuilder.make[Double]
  val numExamples = data.count()
  val costFun =
    new CostFun(data, gradient, updater, regParam, numExamples)
  val lbfgs = new BreezeLBFGS[BDV[Double]](maxNumIterations, numCorrections, convergenceTol)
  val states =
    lbfgs.iterations(new CachedDiffFunction(costFun), initialWeights.asBreeze.toDenseVector)
  var state = states.next()
  while (states.hasNext) {
    lossHistory += state.value
    state = states.next()
  }
  lossHistory += state.value
  val weights = Vectors.fromBreeze(state.x)
  val lossHistoryArray = lossHistory.result()
  (weights, lossHistoryArray)
}
再回头看LBFGS几个内部参数就简单明了,numCorrections即控制输入变量和梯度变量的差值要缓存最近的多少次,convergenceTol即收敛精度。

分布式机器学习思想主要体现在

1、模型参数的共享和同步(使用Spark broadcast机制实现)。

2、分布式的梯度求解,先求解各分区上单个样本的梯度值,再聚合得到总的梯度值(通过treeAggregate算子实现)。之后在Drvie端调用updater来更新模型参数。
————————————————
版权声明:本文为CSDN博主「大愚若智_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zbc1090549839/article/details/64920424

spark.mllib:Optimizer相关推荐

  1. spark.mllib:GradientBoostedTrees

    Gradient-Boosted Trees(GBT或者GBDT) 和 RandomForests 都属于集成学习的范畴,相比于单个模型有限的表达能力,组合多个base model后表达能力更加丰富. ...

  2. spark.mllib:NaiveBayes

    朴素贝叶斯模型简述: 贝叶斯模型通过使用后验概率和类的概率分布来估计先验概率,具体的以公式表达为 P(Y)可以使用训练样本的类分布进行估计.如果X是单特征也很好估计,但如果X={x1,x2,..,xn ...

  3. spark.mllib:回归算法

    Spark实现了三类线性回归方法: 1.LinearRegression:普通线性回归模型 2.LassoRegression:加L1正则化的线性回归 3.RidgeRegression:加L2正则化 ...

  4. spark.mllib:bagging方法

    在训练集成分类器时,关键的一步在于如何从全训练样本集中构建子样本集提供给子分类器进行训练.目前主流的两种子样本集构造方式是bagging方法和boosting方法.bagging方法的思想是从全样本集 ...

  5. 机器学习_机器不学习:从Spark MLlib到美图机器学习框架实践

    / 机器学习简介 / 在深入介绍 Spark MLlib 之前先了解机器学习,根据维基百科的介绍,机器学习有下面几种定义: 机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经 ...

  6. spark.mllib源码阅读:GradientBoostedTrees

    Gradient-Boosted Trees(GBT或者GBDT) 和 RandomForests 都属于集成学习的范畴,相比于单个模型有限的表达能力,组合多个base model后表达能力更加丰富. ...

  7. Spark大数据分析与实战:基于Spark MLlib 实现音乐推荐

    Spark大数据分析与实战:基于Spark MLlib 实现音乐推荐 基于Spark MLlib 实现音乐推荐 一.实验背景: 熟悉 Audioscrobbler 数据集 基于该数据集选择合适的 ML ...

  8. Spark MLlib介绍

    Spark MLlib介绍 Spark之所以在机器学习方面具有得天独厚的优势,有以下几点原因: (1)机器学习算法一般都有很多个步骤迭代计算的过程,机器学习的计算需要在多次迭代后获得足够小的误差或者足 ...

  9. Spark MLlib 机器学习

    本章导读 机器学习(machine learning, ML)是一门涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多领域的交叉学科.ML专注于研究计算机模拟或实现人类的学习行为,以获取新知识.新 ...

最新文章

  1. 使用ecshop电子商务系统的100个小问题
  2. 脚本征集大赛开启啦!100%有奖!
  3. 自相关矩阵和互相关矩阵的matlab实现
  4. js 获取select 中option 的个数
  5. Zebra 命令模式分析2
  6. 【android自定义控件】ProgressBar自定义
  7. 彩翼系列-彩票分析软件源代码(双色球,排三,排五,3D,22选5,30选7)源代码
  8. jquery实现进度条
  9. 《软件架构与设计模式》思维导图
  10. java代码格式化的快捷键设置_如何使用VS中的快捷键快速格式化代码使好看,整齐...
  11. 效率倍升:逐浪HMS主题大师1.2-全渠道自动打包、快速传送、锁屏提取、资源审计,移动主题设计辅助利器(全面支持华V米O)
  12. vue实现横向时间轴组件
  13. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Duplicate entr
  14. 罗永浩 AR 创业公司估值 10 亿;​苹果宣布加大 AppStore 广告推送量;​Node.js 19 发布|极客头条...
  15. Redis安装(Ubuntu)
  16. 计算机专硕考数一英一的学校有哪些,这所211专硕改考数一英一!部分院校初试科目调整...
  17. 判断三个数是否能构成三角形_七年级 初一下册数学三角形专题复习提纲及经典例题...
  18. 嵌入式系统考试复习大全
  19. CodeGear公司正式推出delphi2007 for win32
  20. Db2 V11设计与调优 --- IBM中文官网

热门文章

  1. Online DDL
  2. 数据结构题:克鲁斯卡尔(Kruscal)算法求最小生成树
  3. mysql 5.6升级8.0_Mysql数据库从5.6.28版本升到8.0.11版本部署项目时遇到的问题及解决方法...
  4. python psutil库安装_安装psutil模块报错安装python-devel
  5. phpstudy mysql端口_完美解决phpstudy安装后mysql无法启动(无需删除原数据库,无需更改任何配置,无需更改端口)直接共存...
  6. 程序员吐槽_某程序员吐槽一程序员大佬竟然放弃百度offer,回老家进烟草公司!是不是脑子有坑?网友:你才脑子有坑!...
  7. ppt演讲计时器_用演示文稿演讲的10个技巧
  8. mac mysql-python 失败_MAC OS安装MySQL-python总是失败,请帮忙看看什么原因?
  9. 微带线特性阻抗计算公式_利用HFSS计算微带线的特性阻抗
  10. 数字类 default 0和 default 0_数字化转型从0到N,只需这三步