算法之美 之 小小方差增量算法带来的大大收益

转载 2015年07月09日 22:29:26

算法之美 之 小小方差增量算法带来的大大收益

http://www.cnblogs.com/yoyaprogrammer/p/delta_variance.html

一个小小的方差增量算法,使得消除持续增长的上百GB的明细数据成为可能,空间效率和时间效率都可得到无以伦比的提升。

下面一码给你重现整个过程,小伙伴们一起激动激动。

背景

搞推荐就要玩好私人定制,要玩好私人定制,就得分析用户的购买和浏览行为。我们系统里某个地方就需要针对每个用户,计算他(她)曾经购买过的所有产品的价格的方差。

来,和你一起回顾下方差的定义。

方差的统计学定义

方差是反应数值型数据离散程度的最重要的指标。

假设X样本的有N个样本值:

x1,x2,...,xN

X样本的平均值计算很简单:

X¯¯¯=1Ni=1Nxi

那么计算X样本的方差的公式如下:

σ2X=1Ni=1N(xiX¯¯¯)2

从表面上看,为了计算一组样本值的方差,需要知道所有样本值明细。

持续增长中的上百GB的明细数据

为了保证及时算出产品价格方差这一重要指标,专门存储了每个用户购买的所有产品的价格,还没到一年,数据量就奔着百GB俱乐部的规模去了。问题来了,如果需要分析更长时间内用户的数据,5年,10年,这数据就上TB。总是有增无减,就不是可持续发展的套路,这个算法套路得改改。

如果方差算法能够像订单数一样不断增量处理,不就万事大吉了吗?

增量方差的推导

假设我们现在有两组样本值,一组为历史样本值:

h1,h2,...,hM

一组为增量样本值:

a1,a2,...,aN

根据之前介绍的方差和均值的定义,我们可以得到两组样本值的如下四个指标:

历史平均值

H¯¯¯=1Mi=1Mhi

历史方差

σ2H=1Mi=1M(hiH¯¯¯)2

增量样本均值

A¯¯¯=1Nj=1Naj

增量样本方差

σ2A=1Nj=1N(ajA¯¯¯)2

目前关键问题在于:

h1,h2,...,hM,a1,a2,...,aN

这组全量样本值的方差是否能够由历史样本和增量样本的指标直接计算得到。下面一码就给你推导推导,看能够做到这点。

首先,全量样本均值的计算如下:

X¯¯¯=1M+Ni=1Mhi+j=1Naj=MH¯¯¯+NA¯¯¯M+N

其次,全量样本方差的计算和推导如下:

σ2=1M+Ni=1M(hiX¯¯¯)2+j=1N(ajX¯¯¯)2=1M+Ni=1M((hiH¯¯¯)(X¯¯¯H¯¯¯))2+j=1N((ajA¯¯¯)(X¯¯¯A¯¯¯))2=1M+N[i=1M((hiH¯¯¯)22(hiH¯¯¯)(X¯¯¯H¯¯¯)+(X¯¯¯H¯¯¯)2)+j=1N((ajA¯¯¯)22(ajA¯¯¯)(X¯¯¯A¯¯¯)+(X¯¯¯A¯¯¯)2)]=1M+N[Mσ2H+M(X¯¯¯H¯¯¯)22(X¯¯¯H¯¯¯)(i=1MhiMH¯¯¯)+Nσ2A+N(X¯¯¯A¯¯¯)22(X¯¯¯A¯¯¯)(j=1NajNA¯¯¯)]=1M+N[Mσ2H+M(X¯¯¯H¯¯¯)2+Nσ2A+N(X¯¯¯A¯¯¯)2]=M[σ2H+(X¯¯¯H¯¯¯)2]+N[σ2A+(X¯¯¯A¯¯¯)2]M+N

从推导出来的公式看,通过两组样本的样本数,均值,方差,完全可以计算出全量样本的方差。

增量方差的实现

毕竟推演公式是尘封多年的技能,还是通过代码验证才能让一码放心。

case class Measures(n: Int, sum: Double, variance: Double) {
  def avg = sum / n

  def appendDelta(delta: Measures): Measures = {
    val newN = this.n + delta.n
    val newSum = this.sum + delta.sum
    val newAvg = newSum / newN

    def partial(m: Measures): Double = {
      val deltaAvg = newAvg - m.avg
      m.n * ( m.variance + deltaAvg * deltaAvg )
    }

    val newVariance = (partial(this) + partial(delta)) / newN

    Measures(newN, newSum, newVariance)
  }
}

Measures包含了样本数,均值,和以及方差,构成了可增量计算方差的要素。同时也用它承载职责“方差增量算法”。

case class Samples(values: Seq[Double]) {
  def measures: Measures = {
    if (values == null || values.isEmpty)
      Measures(0, 0d, 0d)
    else
      Measures(values.length, values.sum, variance)
  }

  private def variance: Double = {
    val n = values.length
    val avg = values.sum / n
    values.foldLeft(0d) { case (sum, sample) =>
      sum + (sample - avg) * (sample - avg)
    } / n
  }
}

Samples解决了如何计算一组样本值所需要的统计指标,按统计学定义直接计算,无增量算法。

object DeltaVarianceUtils {
  def main(args: Array[String]): Unit = {
    implicit val arrayToSamples = (values: Array[Double]) => Samples(values)

    val historicalSamples = Array(1.5d, 3.4d, 7.8d, 11.6d)
    val deltaSamples = Array(9.4d, 4.2d, 35.6d, 77.9d)

    println("Variance: "
      + (historicalSamples ++ deltaSamples).measures.variance
    )
    println("Variance calculated by delta algorithm: "
      + historicalSamples.measures.appendDelta(deltaSamples.measures).variance
    )
  }
}

第一种是通过传统的统计学定义直接计算方差。先把历史样本值和增量样本值合并,然后计算方差。

第二种是增量化的方差算法。把历史样本值转换成Measures,也就是可增量计算方差的要素,然后将增量样本值对应的measures要素合并进来,得到最终的方差。

运行结果如下:

Variance: 598.2168750000002
Variance calculated by delta algorithm: 598.2168750000001

大大的收益

方差算法增量化后,从空间效率看:每个用户不需要再存任何产品价格明细,只需要存Measures中的三要素(历史样本数,历史价格总和,历史样本方差)即可,需要记录的数据量对每个用户是恒定的,哪怕是需要分析100年的用户数据,这个算法也不怕了。

从时间效率看:每次计算方差时,可以完全重用历史样本的指标,省了绝大部分基于样本值的计算。

方差算法增量化后,无论空间还是时间效率,都得到了非常大的提升。

对于算法之美,小伙伴们,你们激动了吗?

相关文章推荐

推荐系统学习之概率算法及其增量算法

谈到推荐吧,我知道的也很少,总括的这种就不吹了。第一个和概率有关的推荐算法应该是**“关联规则挖掘”**,就是置信度、支持度那个,我就不多言了,接下来一个的则是**“Page Rank”**,这一个方...
  • axuanwu
  • axuanwu
  • 2016年01月25日 19:30
  • 1519

增量学习

最近在看周老师的机器学习看到关于增量学习的概念,之前没有接触过就在网上查了查,现在总结一下 增量学习(Incremental Learning)是指一个学习系统能不断地从新样本中学习新的知识...
  • Losteng
  • Losteng
  • 2016年04月04日 19:37
  • 5687

GC增量算法的理论与实践

  author:tuiye@126.com以MMgc为例 一垃圾收集       垃圾收集(Garbage Collection,GC)是一种自动打扫和清除内存垃圾的技术,它可以有效防范动态内存分配...

scala学习笔记07--样本类(case class)和模式匹配

样本类:添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:     1.添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Va...

Oracle中用exp/imp命令参数详解

【用 exp 数 据 导 出】: 1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中    exp system/manager@TEST   ...

风险风险之深入分析协方差意义与算法

我们先回忆一下期望、方差与标准查的

基于最大类间方差的分割算法

  • 2016年11月29日 20:38
  • 8KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法之美 之 小小方差增量算法带来的大大收益
举报原因:
原因补充:

(最多只允许输入30个字)