1.理解
  问题定义可以简化如下:在不知道文件总行数的情况下,如何从文件中随机的抽取一行?

  首先想到的是我们做过类似的题目吗?当然,在知道文件行数的情况下,我们可以很容易的用C运行库的rand函数随机的获得一个行数,从而随机的取出一行,但是,当前的情况是不知道行数,这样如何求呢?我们需要一个概念来帮助我们做出猜想,来使得对每一行取出的概率相等,也即随机。这个概念即蓄水池抽样(Reservoir Sampling)。

水塘抽样算法(Reservoir Sampling)思想:
  在序列流中取一个数,如何确保随机性,即取出某个数据的概率为:1/(已读取数据个数)

  假设已经读取n个数,现在保留的数是Ax,取到Ax的概率为(1/n)。

  对于第n+1个数An+1,以1/(n+1)的概率取An+1,否则仍然取Ax。依次类推,可以保证取到数据的随机性。

  数学归纳法证明如下:

    当n=1时,显然,取A1。取A1的概率为1/1。

  假设当n=k时,取到的数据Ax。取Ax的概率为1/k。

   当n=k+1时,以1/(k+)的概率取An+,否则仍然取Ax。

 (1)如果取Ak+1,则概率为1/(k+1);

 (2)如果仍然取Ax,则概率为(1/k)*(k/(k+1))=1/(k+1)

  所以,对于之后的第n+1个数An+1,以1/(n+1)的概率取An+1,否则仍然取Ax。依次类推,可以保证取到数据的随机性。

在序列流中取k个数,如何确保随机性,即取出某个数据的概率为:k/(已读取数据个数)

  建立一个数组,将序列流里的前k个数,保存在数组中。(也就是所谓的”蓄水池”)

  对于第n个数An,以k/n的概率取An并以1/k的概率随机替换“蓄水池”中的某个元素;否则“蓄水池”数组不变。依次类推,可以保证取到数据的随机性。

  数学归纳法证明如下:

    当n=k是,显然“蓄水池”中任何一个数都满足,保留这个数的概率为k/k。

    假设当n=m(m>k)时,“蓄水池”中任何一个数都满足,保留这个数的概率为k/m。
    当n=m+1时,以k/(m+1)的概率取An,并以1/k的概率,随机替换“蓄水池”中的某个元素,否则“蓄水池”数组不变。则数组中保留下来的数的概率为:

  所以,对于第n个数An,以k/n的概率取An并以1/k的概率随机替换“蓄水池”中的某个元素;否则“蓄水池”数组不变。依次类推,可以保证取到数据的随机性。

Spark中的水塘抽样算法(Reservoir Sampling)
  spark的Partitioner子类RangePartitioner中有用到Reservoir Sampling抽样算法(org.apache.spark.RangePartitioner#sketch).

spark的util中有reservoirSampleAndCount方法(org.apache.spark.util.random.SamplingUtils#reservoirSampleAndCount)

源码为:

/**
* Reservoir sampling implementation that also returns the input size.
*
* @param input input size
* @param k reservoir size
* @param seed random seed
* @return (samples, input size)
*/
def reservoirSampleAndCount[T: ClassTag](
input: Iterator[T],
k: Int,
seed: Long = Random.nextLong())
: (Array[T], Int) = {
val reservoir = new Array[T](k)
// Put the first k elements in the reservoir.
var i =
while (i < k && input.hasNext) {
val item = input.next()
reservoir(i) = item
i +=
} // If we have consumed all the elements, return them. Otherwise do the replacement.
if (i < k) {
// If input size < k, trim the array to return only an array of input size.
val trimReservoir = new Array[T](i)
System.arraycopy(reservoir, , trimReservoir, , i)
(trimReservoir, i)
} else {
// If input size > k, continue the sampling process.
val rand = new XORShiftRandom(seed)
while (input.hasNext) {
val item = input.next()
val replacementIndex = rand.nextInt(i)
if (replacementIndex < k) {
reservoir(replacementIndex) = item
}
i +=
}
(reservoir, i)
}
}

代码实现思路比较简单,新建一个k大小的数组reservoir,如果元数据中数据少于k,直接返回原数据数组和原数据个数。如果大于,则对接下来的元素进行比较,随机生成一个数i,如果这个数小于k,则替换数组reservoir中第i个数,直至没有元素,则返回reservoir的copy数组。

2.代码:
测试org.apache.spark.util.random.SamplingUtils$#reservoirSampleAndCount方法:

package org.apache.spark.sourceCode.partitionerLearning

import org.apache.spark.util.SparkLearningFunSuite
import org.apache.spark.util.random.SamplingUtils import scala.util.Random class reservoirSampleAndCountSuite extends SparkLearningFunSuite {
test("reservoirSampleAndCount") {
val input = Seq.fill()(Random.nextInt())
val (sample1, count1) = SamplingUtils.reservoirSampleAndCount(input.iterator, )
assert(count1 === )
assert(input === sample1.toSeq) // input size == k
val (sample2, count2) = SamplingUtils.reservoirSampleAndCount(input.iterator, )
assert(count2 === )
assert(input === sample2.toSeq) // input size > k
val (sample3, count3) = SamplingUtils.reservoirSampleAndCount(input.iterator, )
assert(count3 === )
assert(sample3.length === )
println(input)
sample3.foreach{each=>print(each+" ")}
} }

3.结果:

List(, , -, -, , -, , -, , , -, -, , -, -, , -, -, -, -, -, -, -, , -, , , , -, -, -, -, , , , , , -, , , -, , , -, -, -, -, -, -, -, , , -, , -, , , , , , -, , , -, , , , , -, , , , -, -, , -, , , , -, , -, , -, -, -, , , , , , , -, -, , -, , , -, -)
- - - -

Spark MLlib之水塘抽样算法(Reservoir Sampling)的更多相关文章

  1. 【算法34】蓄水池抽样算法 (Reservoir Sampling Algorithm)

    蓄水池抽样算法简介 蓄水池抽样算法随机算法的一种,用来从 N 个样本中随机选择 K 个样本,其中 N 非常大(以至于 N 个样本不能同时放入内存)或者 N 是一个未知数.其时间复杂度为 O(N),包含 ...

  2. 蓄水池抽样算法 Reservoir Sampling

    2018-03-05 14:06:40 问题描述:给出一个数据流,这个数据流的长度很大或者未知.并且对该数据流中数据只能访问一次.请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等. 问题求 ...

  3. Spark MLlib中KMeans聚类算法的解析和应用

    聚类算法是机器学习中的一种无监督学习算法,它在数据科学领域应用场景很广泛,比如基于用户购买行为.兴趣等来构建推荐系统. 核心思想可以理解为,在给定的数据集中(数据集中的每个元素有可被观察的n个属性), ...

  4. spark.mllib源代码阅读-优化算法1-Gradient

    Spark中定义的损失函数及梯度,在看源代码之前,先回想一下机器学习中定义了哪些损失函数,毕竟梯度求解是为优化求解损失函数服务的. 监督学习问题是在如果空间F中选取模型f作为决策函数.对于给定的输入X ...

  5. 水塘抽样(Reservoir Sampling)问题

    水塘抽样是一系列的随机算法,其目的在于从包含n个项目的集合S中选取k个样本,其中n为一很大或未知的数量,尤其适用于不能把所有n个项目都存放到主内存的情况. 在高德纳的计算机程序设计艺术中,有如下问题: ...

  6. Reservoir Sampling - 蓄水池抽样问题

    问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...

  7. 算法系列:Reservoir Sampling

    copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  8. Reservoir Sampling - 蓄水池抽样

    问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...

  9. 用Spark学习矩阵分解推荐算法

    在矩阵分解在协同过滤推荐算法中的应用中,我们对矩阵分解在推荐算法中的应用原理做了总结,这里我们就从实践的角度来用Spark学习矩阵分解推荐算法. 1. Spark推荐算法概述 在Spark MLlib ...

随机推荐

  1. openresty的安装和使用

    1,简介 OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,是一个强大的 Web 应用服务器,在性能方面,OpenResty可以 快速构造出足以 ...

  2. 【CF553E】Kyoya and Train 最短路+cdq分治+FFT

    [CF553E]Kyoya and Train 题意:有一张$n$个点到$m$条边的有向图,经过第i条边要花$c_i$元钱,经过第i条边有$p_{i,k}$的概率要耗时k分钟.你想从1走到n,但是如果 ...

  3. 英文写作强调技巧:alliteration, assonance, consonance

    alliteration 安排两个以上首字母相同的词相邻 例: The bouncing ball went high into the sky. (In this example, the &quo ...

  4. ubuntu部署git

    先更新本机内置的程序. sudo apt-get updatesudo apt-get upgrade再判断系统是否内置了add-apt-repository命令,如果没有执行下列命令安装 sudo ...

  5. 精彩看点 | GIAC大会PPT+视频合集全量放送!

    GIAC是中国互联网技术领域的行业盛事,每年从互联网架构最热门的系统架构设计.人工智能.机器学习.工程效率.区块链.分布式架构等领域甄选前沿有典型代表的技术创新及研发实践的架构案例,分享他们在本年度最 ...

  6. 初试 Entity Framework Core 的多对多映射

    今天在博问中看到一个关于 EF Core 的提问 ef core 2.0 多对多查询的问题,由于还没使用过 EF Core 的多对多映射,于是参考 EF Core 帮助文档快速写了个 .net cor ...

  7. Concurrent Execution

    Concurrent Execution — Python 3.7.2 documentation https://docs.python.org/3/library/concurrency.html

  8. JavaScripts 的bom对象

    bom:即broswer object model(浏览器对象模型),由五个对象组成:        Window:对象表示浏览器中打开的窗口 最顶层对象.       Navigator :浏览器对 ...

  9. CSS盒子模型(简要了解)

    CSS中, Box Model叫盒子模型(或框模型),Box Model规定了元素框处理元素内容(element content).内边距(padding).边框(border) 和 外边距(marg ...

  10. [administrative] windows 下制作USB启动盘的工具

    arch魔教的文档:  https://wiki.archlinux.org/index.php/USB_flash_installation_media windows 下的 dd: https:/ ...