蓄水池演算法

2021-09-14 04:02:13 字數 1767 閱讀 9743

最近有個需求,需要從不固定大小的資料集中取固定數量的資料作為樣本,有個同學提到了蓄水池演算法,於是了解了一下。

蓄水池演算法,本身是為了解決海量資料的隨機抽樣問題,在演算法領域應用還是挺廣泛的,由於資料本身是有權重,又出現了加權蓄水池演算法。

問題描述: 給定乙個不固定長度的資料集合sequence,從中等概率地抽取k個元素作為樣本返回

問題思路: 先把樣本填滿,然後不斷往樣本裡面等概率替換元素

演算法實現

def reservior_sampling(sequence, k):

n = len(sequence)

if k > n:

return sequence

sample = list()

for i in range(k):

for i in range(k, n):

j = random.randint(0, i)

if j >= k:

continue

sample[j] = sequence[i]

return sample

這裡需要注意的是往樣本裡面替換元素的時候,第i個元素能被選中用來替換的概率是k / i + 1,這樣就能保證每個元素被選中的機會都是均等的

問題描述: 給定乙個不固定長度的非常大的資料集合sequence,集合中每個元素包含乙個權重weight,按照權重從集合中抽取k個元素返回

問題思路: 和蓄水池演算法的思路一樣,先把樣本填滿,然後不斷地按照權重替換元素

演算法實現

def weighted_reservior_sampling_achao(sequence, k):

n = len(sequence)

if k > n:

return sequence

wsum = 0

sample = list()

for i in range(k):

wsum += sequence[i]['weight'] / k

for i in range(k, n):

wsum += sequence[i]['weight'] / k

p = sequence[i]['weight'] / wsum

j = random.random()

if j <= p:

sample[random.randint(0, k-1)] = sequence[i]

return sample

這裡第i個元素被選中用來替換的概率是sequence[i].weight * k / sum(sequence[0:i+1].weight),當所有權重都一致的時候,就和蓄水池演算法是一致的了。

這裡面有個小問題,就是一開始用來填充樣本的資料,其實是等概率的,這樣會導致,填充樣本的資料權重失效,但是這個問題只在資料集合較小(準確地說klen(sequence)比較接近)的情況下才會有比較明顯的缺陷,在海量資料集的情況下,這種影響是微乎其微的。

完整**:

reservoir sampling:

蓄水池演算法

參考文章 問題定義 給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的 出現概率均等 求解蓄水池抽樣演算法 該演算法是針對從乙個序列中隨機抽取不重複的k個數,保證每個數被抽取...

蓄水池演算法

適用情況 從n個數中等概率隨機取出k個數,n很大,k也很大 n不固定增量型 內容 當i屬於1 k i入池 當i k i以概率k i決定是否進入池,1 k概率剔除池中乙個數 證明 1 當i 當k個數時,i留下概率 1 當k 1個數時,i被淘汰的概率 1 k k k 1 1 k 1 i留下概率 1 1 ...

蓄水池演算法

在乙個未知的池子裡選1個數字,讓他們被選擇概率一致。假設n的時候,前n個數字被選擇的概率都是1n 當為n 1時候,當前n 1這個數,我們選擇的概率是1n 1,其餘數字的概率是nn 1,那麼一共有n個數字的概率是1n 所以 n 1n 1 n 1 1n 1 具體演算法 使用的方式是i random.ra...