蓄水池取樣

2021-09-10 08:34:48 字數 1707 閱讀 7114

***

現在有一組數,不知道這組數的總量有多少,請描述一種演算法能夠在這組資料中隨機抽取k個數,使得每個數被取出來的概率相等。

如果這組數有n個,那麼每個數字取到的概率就是k/n,但是這個問題的難點在於不知道這組數的總數,也就是不知道n,那麼該怎麼計算每個數取到的概率呢

用python實現一下蓄水池演算法,由於蓄水池演算法是在事先不知道總量的情況下抽樣的,所以定義乙個方法來接收單個元素,並且把這個方法放在類中,以持有取樣後的資料。

import random

class

reservoirsample

(object):

def__init__

(self, size)

: self._size = size

self._counter =

0 self._sample =

deffeed

(self, item)

: self._counter +=

1# 第i個元素(i <= k),直接進入池中

iflen

(self._sample)

< self._size:

# 引用傳遞

return self._sample

# 第i個元素(i > k),以k / i的概率進入池中

rand_int = random.randint(

1, self._counter)

if rand_int <= self._size:

self._sample[rand_int -1]

= item

return self._sample

測試**

接下來實現乙個測試用例驗證實現的演算法是否正確,既然是隨機抽樣,無法通過單詞測試來驗證是否正確,所以通過多次執行的方式來驗證,比如從1-10裡隨機取樣3個數,然後執行10000次取樣,如果演算法正確,最後結果中1-10被取樣的次數應該是相同的,都是3000上下。

import unittest

from collections import counter

from reservoir_sample import reservoirsample

class

testmain

(unittest.testcase)

:def

test_reservoir_sample

(self)

: samples =

for i in

range

(10000):

sample =

rs = reservoirsample(3)

for item in

range(1

,11):

sample = rs.feed(item)

samples.extend(sample)

r = counter(samples)

print

(r)if __name__ ==

'__main__'

: unittest.main(

)

蓄水池取樣

問題描述 現實生活中有很多流式資料,在流式資料上取樣可以抽象為 設幾個中元素個數為n,並且n在不斷的增大,如何在集合中採集k個樣本,使得每個樣本被採集到的概率相等 k n 蓄水池抽樣法 演算法思路是,先構造乙個可以放k個元素的池子,池子中一開始放元素1 k。對於k 1 n 以k n的概率決定是否被替...

隨機取樣 蓄水池問題

看了多篇講解蓄水池問題的文章,感覺下面 的這一篇是證明最為嚴謹的。如何在事先不知道文字檔案行數n的情況下讀取該檔案,從中隨機選擇並輸出一行?事先不知道n的大小,但是一次可以看到這n個物件 即蓄水池抽樣 reservoir sampling 問題 證明如下 問題 證明當前任意一行為取出行的概率為1 i...

蓄水池問題

蓄水池問題描述 假設有n個數,從中隨機抽取k個數字,如果保證抽取的過程是等概率的?其中n是不固定的 類似問題 1.從100個數字抽取20個,如果向100個數字中再增加20個呢?2.給你乙個長度為n的鍊錶,n很大,但你不知道n有多大,你的任務是從這n個元素中取出k個元素,你只能遍歷一次這個鍊錶,演算法...