成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

用Python寫算法 | 蓄水池算法實(shí)現(xiàn)隨機(jī)抽樣

陳偉 / 2406人閱讀

摘要:輸出的結(jié)果如下上面輸出了每個(gè)數(shù)字被取樣到的次數(shù),通過圖表可以清晰的看到分布情況可以看出蓄水池算法對于隨機(jī)抽樣還是非常適合的,每個(gè)元素的抽樣概率都相同。

現(xiàn)在有一組數(shù),不知道這組數(shù)的總量有多少,請描述一種算法能夠在這組數(shù)據(jù)中隨機(jī)抽取k個(gè)數(shù),使得每個(gè)數(shù)被取出來的概率相等。

如果這組數(shù)有n個(gè),那么每個(gè)數(shù)字取到的概率就是k/n,但是這個(gè)問題的難點(diǎn)在于不知道這組數(shù)的總數(shù),也就是不知道n,那么該怎么計(jì)算每個(gè)數(shù)取到的概率呢?

蓄水池算法

游泳池(蓄水池)大家都不陌生,有些游泳池中的水是活的,有入水管也有出水管,那么和泳池體積相當(dāng)?shù)乃鬟^之后,是不是泳池中所有的水都會被替換呢?當(dāng)然不是,有的水在泳池中可能會存留很久,有的可能剛進(jìn)去就流走了。仿照這種現(xiàn)象,蓄水池抽樣算法誕生了,蓄水池算法的關(guān)鍵在于保證流入蓄水池的水和已經(jīng)在池中的水以相同的概率留存在蓄水池中。并且蓄水池算法可以在不預(yù)先知道總量的情況下,在時(shí)間復(fù)雜度O(N)的情況下,來解決這類采樣問題。

核心原理

這一部分涉及公式,為了保證效果直接貼了圖過來。

Python實(shí)現(xiàn)

接下來嘗試用Python實(shí)現(xiàn)一下蓄水池算法,由于蓄水池算法是在事先不知道總量的情況下抽樣的,所以定義一個(gè)方法來接收單個(gè)元素,并且把這個(gè)方法放在類中,以持有采樣后的數(shù)據(jù)。

import random


class ReservoirSample(object):

    def __init__(self, size):
        self._size = size
        self._counter = 0
        self._sample = []

    def feed(self, item):
        self._counter += 1
        # 第i個(gè)元素(i <= k),直接進(jìn)入池中
        if len(self._sample) < self._size:
            self._sample.append(item)
            return self._sample
        # 第i個(gè)元素(i > k),以k / i的概率進(jìn)入池中
        rand_int = random.randint(1, self._counter)
        if rand_int <= self._size:
            self._sample[rand_int - 1] = item
        return self._sample
測試代碼

接下來實(shí)現(xiàn)一個(gè)測試用例驗(yàn)證實(shí)現(xiàn)的算法是否正確,既然是隨機(jī)抽樣,無法通過單詞測試來驗(yàn)證是否正確,所以通過多次執(zhí)行的方式來驗(yàn)證,比如從1-10里隨機(jī)取樣3個(gè)數(shù),然后執(zhí)行10000次取樣,如果算法正確,最后結(jié)果中1-10被取樣的次數(shù)應(yīng)該是相同的,都是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()

輸出的結(jié)果如下

Counter({7: 3084, 6: 3042, 10: 3033, 3: 3020, 8: 3016, 5: 2997, 4: 2986, 2: 2972, 9: 2932, 1: 2918})

上面輸出了每個(gè)數(shù)字被取樣到的次數(shù),通過圖表可以清晰的看到分布情況

可以看出蓄水池算法對于隨機(jī)抽樣還是非常適合的,每個(gè)元素的抽樣概率都相同。

代碼

上述的算法和測試代碼已經(jīng)放在Github,可以直接下載使用。

關(guān)注公眾號【Python私房菜】

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/42134.html

相關(guān)文章

  • leetcode382. Linked List Random Node

    摘要:題目要求要求從單鏈表中,隨機(jī)返回一個(gè)節(jié)點(diǎn)的值,要求每個(gè)節(jié)點(diǎn)被選中的概率是相等的。假如一共有個(gè)物品,需要從其中挑選出個(gè)物品,要求確保個(gè)物品中每個(gè)物品都能夠被等概率選中。對于這種等概率問題,簡答的做法是通過隨機(jī)數(shù)獲取選中物品的下標(biāo)。 題目要求 Given a singly linked list, return a random nodes value from the linked li...

    xiaodao 評論0 收藏0
  • 經(jīng)典算法隨機(jī)抽樣

    摘要:最近發(fā)現(xiàn)兩個(gè)比較有意思的隨機(jī)抽樣算法,分享一下隨機(jī)抽樣且保持有序需求一家公司購買了他們的第一批電腦,該公司的業(yè)務(wù)主要是民意調(diào)查,現(xiàn)在要開發(fā)一個(gè)程序程序的輸入是選區(qū)名列表以及整數(shù),輸出是隨機(jī)選擇的個(gè)選區(qū)名列表。 最近發(fā)現(xiàn)兩個(gè)比較有意思的隨機(jī)抽樣算法,分享一下 1. 隨機(jī)抽樣且保持有序 需求: 一家公司購買了他們的第一批電腦,該公司的業(yè)務(wù)主要是民意調(diào)查,現(xiàn)在要開發(fā)一個(gè)程序:程序的輸入是選區(qū)...

    awesome23 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<