1. 程式人生 > >機器學習--蓄水池抽樣與加權抽樣演算法

機器學習--蓄水池抽樣與加權抽樣演算法

學習一下蓄水池抽樣以及加權抽樣演算法

1.蓄水池抽樣

如果資料總量是有限的,隨機抽樣k個值,可以直接利用隨機數產生器來產生。如果數量總量是不斷增加的,記憶體並不能完全存放所有資料,此時若隨機產生k個值可以採用蓄水池抽樣演算法。

1.從一個數據流中隨機取出一個數,要求每個數被取到的概率相等

第一個數以概率1取值,第二個數以1/2概率替換,第三個數以1/3概率替換。。。。直到第n個數

第一個數被取到的概率  第一個數取到並且後面沒有被替換掉

1*1/2*2/3*3/4.......(n-1)/n=1/n

第k個數,最後被取到的概率    第k個數被取到,並且後面沒有被替換掉

1/k * k/k+1 * k+1/k+2 *.... n-1/n = 1/n

即每個數被取到的概率是相等的

python程式設計實現:

def random(num=[]):
    import numpy as np
    i = 2
    r = num[1]
    while i<len(num):
        #print (i)
        #print (np.random.randint(1, i))		
        if np.random.randint(1, i)==i:
            r = num[i]
        i = i + 1
        #print (i)	    
    print (r)

randint(a,b)可以產生一個[a,b]的隨機數,下式成立的概率應該為1/i

np.random.randint(1, i)==i

後來測試發現randint(a,b)不會產生等於b的隨機數,修改右端點為i+1 這樣np.random.randint(1, i+1)即可產生1--i的隨機數,等於1的概率即為1/i

def random(num=[]):
    import numpy as np
    i = 2
    r = num[1]
    while i<len(num):
        #print (i)
        #print (np.random.randint(1, i+1))		
        if np.random.randint(1, i+1)==1:
            r = num[i]
        i = i + 1
        #print (i)	    
    print (r)

後來查了一下,發現自己搞錯了,randint(a,b)可以產生一個[a,b)的隨機數,右邊界取不到

2.從一個數據流中隨機選取k個數,要求每個被選取到的概率相等

蓄水池取樣演算法:

先將k個數放入到蓄水池中,後面的每一個數(>k)都已k/k+1的概率換入蓄水池,換入時隨機選取蓄水池的一個數換出

第一個數被選中的概率是   第一個數被選中*(後面的數沒有被選中+後面的數被選中但是沒有替換掉1)

1 * (1/k+1 * k-1/k + k/k+1)*(1/k+2 * k-1/k + k+1/k+2) *......  *(1/n*k-1/k +n-1/n)=  k/n;

對於資料流不斷增加,資料中某個值\alpha,被選中的概率是:

當資料小於\alpha肯定不會選中,因為資料中沒有該值\alpha

當資料流等於\alpha時其被選中的概率為k/\alpha;

當資料流大於\alpha時,要保證後面的每個數不會替換掉\alpha

程式碼如下:

def randomk(k, num=[]):
    import numpy as np
	#座標索引不會取到右端點
    r = num[1:k+1]
    i = k+1
    while i<len(num):
        j = np.random.randint(1, i+1)
        if j <= k:
            r[j] = num[i]
        i = i + 1
    print (r)

j = np.random.randint(1, i+1) 產生[1,i]的隨機數  j<=k的概率為k/i,以該概率將蓄水池中j位置換為num[i]元素即可。

以上實現了蓄水池抽樣,特別是資料來源不確定時,下面是加權抽樣,即每個資料點都有一個權重,可以簡單分為資料來源有限以及無限的情況。

2.加權抽樣

演算法1:資料集有限:

wn被選中的概率為:wn/(w1 + w2 + ··· + wn)  wn-1被選中的概率為:wn-1/(w1 + w2 + ··· + wn-1)

每一個標籤依次選中的可能性為:

演算法2:資料集有限

給定資料以及相應權重,利用權重以及隨機數來給每一個數據打分

最終挑選出分值最大的k個數作為最終結果返回。

演算法3: 資料集有限

利用指數分佈:

為每一個標籤生成一個指數分佈\lambda為標籤權重,然後每個分佈隨機產生一個數值,挑選隨機數值最大的k個標籤返回即可。

演算法4:資料集無限

當資料集無限時,不能採用演算法1來計算所有標籤的分值,可以採用蓄水池抽樣演算法來實現。

為每一個樣本生成一個分數: 

如果不足 k 個,直接儲存

如果已經有 k 個,如果 ki 比已有的結果裡最小那個分數大,就替換

下面依次給出演算法1和2的正確性

然後給出演算法4的正確性

演算法2和演算法1等效性的證明:

Ui為(0,1)之間隨機數  wi為資料i的權重,Xi為資料i的分數  \alpha為[0,1]之間的一個實數,現在證明以上命題。

定義分佈函式:

概率密度函式為:

n=1時有:

n=2時有:

假設n=k時成立:

當n=k+1時:

參考文獻:

大神論文:《Weighted random sampling with a reservoir》