机器学习中的数学——蓄水池抽样算法(Reservoir Sampling Algorithm)

分类目录:《机器学习中的数学》总目录


蓄水池抽样算法(Reservoir Sampling Algorithm)解决了未知长度数据的均匀抽样问题,即:给定一个数据流,数据流长度 N N N很大,且 N N N直到处理完所有数据之前都不可知,请问如何在只遍历一遍数据的情况下,能够随机选取出 n n n个不重复的数据,且每个数据被取到的概率都为 n N \frac{n}{N} Nn

这个问题有3个主要难点:

  • 数据流长度 N N N很大且不可知,不能一次性存入内存
  • 算法时间复杂度为 O ( N ) O(N) O(N)
  • 随机选取 n n n个数,每个数被选中的概率为 n N \frac{n}{N} Nn

第1点主要说明由于我们无法直接确定 N N N,导致我们无法直接求出每个数被取到的概率 n N \frac{n}{N} Nn,也就不能直接取 N N N内的 n n n个随机数,然后按索引取出数据。第2点限制了不能先遍历一遍得到数据总量 N N N,然后分块存储数据,再随机选取。第3点是数据选取绝对随机的保证。

蓄水池抽样算法(Reservoir Sampling Algorithm)
输入:数组 A r r Arr Arr
( 1 )初始化长度为 n n n结果数组 A A A
( 2 )初始化数组读入索引 i = 0 i=0 i=0
( 3 ) while 数组 A r r Arr Arr未遍历到末尾
( 4 ) \quad if i < n i< n i<n
( 5 ) \qquad A r r [ i ] Arr[i] Arr[i]加入到结果数组 A A A
( 6 ) \quad else
( 7 ) \qquad [ 0 , i ] [0, i] [0,i]随机取一个整数 d d d,若 d d d [ 0 , n − 1 ] [0, n-1] [0,n1]范围内,则将 A r r [ i ] Arr[i] Arr[i]存入 A [ d ] A[d] A[d]
( 8 ) \quad i = i + 1 i=i+1 i=i+1
( 9 )return 数组 A A A

蓄水池抽样算法(Reservoir Sampling Algorithm)的精妙之处在于,对于未知长度 N N N的数组,其每个数被选中的概率都为 n N \frac{n}{N} Nn。设 i i i为未知长度数组的数据索引(从0开始),则:

  • i < n i<n i<n:这些数据直接被存入结果数组 A A A,遍历结束时仍留在结果数组 A A A的概率为: P = n n + 1 × n + 1 n + 2 × ⋯ × N − 1 N = n N P=\frac{n}{n+1}\times\frac{n+1}{n+2}\times\cdots\times\frac{N-1}{N}=\frac{n}{N} P=n+1n×n+2n+1××NN1=Nn
  • i ≥ n i\geq n in:这些数据被存入数组的概率为 n i + 1 \frac{n}{i+1} i+1n,被存入数组的概率为且遍历结束时仍留在结果数组 A A A的概率为: P = n i + 1 × i + 1 i + 2 × ⋯ × N − 1 N = n N P=\frac{n}{i+1}\times\frac{i+1}{i+2}\times\cdots\times\frac{N-1}{N}=\frac{n}{N} P=i+1n×i+2i+1××NN1=Nn

若数据量过于庞大,需要使用 K K K台机器处理数据,则可以使用分布式蓄水池抽样算法:

分布式蓄水池抽样算法
输入:数据流 A r r Arr Arr;机器总数 K K K
( 1 )将数据流分成 K K K份: A r r 1 Arr_1 Arr1 A r r 2 Arr_2 Arr2 ⋯ \cdots A r r k Arr_k Arrk或依次向 K K K台机器输入数据
( 2 )每台机器单独使用蓄水池抽样算法,抽样 n n n个数据 A 1 A_1 A1 A 2 A_2 A2 ⋯ \cdots A K A_K AK,并统计单台机器的数据总量 N 1 N_1 N1 N 2 N_2 N2 ⋯ \cdots N K N_K NK
( 3 ) 计算数据总量 N = N 1 + N 2 + ⋯ + N K N=N_1+N_2+\cdots+N_K N=N1+N2++NK并初始化长度为 n n n最终结果数组 A A A
( 4 ) for    i = 1 : n \ \ i=1:n   i=1:n
( 5 ) \quad [ 1 , N ] [1, N] [1,N]随机取一个整数 d d d
( 6 ) \quad d ≤ N 1 d\leq N_1 dN1,则从 A 1 A_1 A1中无放回的随机抽取一个数据放入最终结果数组 A A A;若 N 1 < d ≤ N 1 + N 2 N_1<d\leq N_1+N_2 N1<dN1+N2,则从 A 2 A_2 A2中无放回的随机抽取一个数据放入最终结果数组 A A A ⋯ \cdots ;若 N 1 + N 2 + ⋯ + N K − 1 < d ≤ N 1 + N 2 + ⋯ + N K N_1 + N_2 + \cdots + N_{K-1}<d\leq N_1 + N_2 + \cdots + N_K N1+N2++NK1<dN1+N2++NK,则从 A K A_K AK中无放回的随机抽取一个数据放入最终结果数组 A A A
( 7 )return 最终结果数组 A A A

我们现在来验证一下分布式蓄水池抽样算法每个数据被抽到的概率是否为 n N \frac{n}{N} Nn:

  • 对于第 k k k台机器中的数据,被抽中到第 k k k台机器的结果数组 A k A_k Ak的概率为 n N k \frac{n}{N_k} Nkn
  • n n n次循环后,每个数据被选入最终结果数组 A A A的概率为 n × n N k × N k N × 1 n = n N n\times\frac{n}{N_k}\times\frac{N_k}{N}\times\frac{1}{n}=\frac{n}{N} n×Nkn×NNk×n1=Nn

猜你喜欢

转载自blog.csdn.net/hy592070616/article/details/127376833