簡體   English   中英

c ++具有頻繁變化概率的離散分布采樣

[英]c++ discrete distribution sampling with frequently changing probabilities

問題:我需要從由某些權重構成的離散分布中進行采樣,例如{w1,w2,w3,..},從而得到概率分布{p1,p2,p3,...},其中pi = wi /(w1 + W2 + ...)。

一些wi的變化非常頻繁,但只有非常低比例的所有wi。 但是,每次發生時,分布本身都必須重新規范化,因此我認為Alias方法不能有效地工作,因為每次都需要從頭開始構建整個分布。

我目前正在考慮的方法是二叉樹(堆方法),其中所有wi都保存在最低級別,然后是兩個級別在更高級別中的總和,依此類推。 所有這些的總和將處於最高級別,這也是歸一化常數。 因此,為了在wi中更改后更新樹,需要進行log(n)更改,以及從分發中獲取樣本的相同數量。

題:

Q1。 你對如何更快地實現它有更好的想法嗎? Q2。 最重要的部分:我正在尋找一個已經完成這項工作的圖書館。

解釋:幾年前我自己做了這個,通過在向量中構建堆結構,但從那時起我學到了很多東西,包括發現庫(:))和容器如map ...現在我需要重寫代碼具有更高的功能,我想這次正確:

所以Q2.1有一個很好的方法可以使c ++地圖不是通過索引進行排序和搜索,而是通過它的元素的累積和(這是我們的樣本,對吧?)。 (這是我目前的理論,我想怎么做,但它不一定要這樣......)

Q2.2也許還有一些更好的方法可以做到這一點? 我會相信這個問題是如此頻繁,我很驚訝我找不到某種能為我做這件事的圖書館......

非常感謝,如果有其他形式的問題,我很抱歉,請指導我,但我花了很長時間看...

-z

編輯:我可能需要刪除或添加元素,但我認為我可以避免它,如果這會產生巨大的差異,因此只留下改變權重的值。

Edit2:權重一般是實數,我不得不考慮是否可以使它們成為整數...

我實際上會使用一組哈希字符串(不記得它的C ++容器,你可能需要實現自己的)。 為每個i放置wi元素,值為“w1_1”,“w1_2”,......全部通過“w1_ [w1]”(即w1元素以“w1_”開頭)。

需要采樣時,使用均勻分布隨機選取一個元素。 如果您選擇了w5_ *,則說您選擇了元素5.由於哈希中的元素數量,這將為您提供所需的分布。

現在,當wi從A變為B時,只需將BA元素添加到散列(如果B> A),或刪除wi的最后AB元素(如果A> B)。

在這種情況下,添加新元素和刪除舊元素是微不足道的。

顯然問題是“隨機挑選一個元素”。 如果你的哈希是一個封閉的哈希,你隨機選擇一個數組單元格,如果它是空的 - 只需再次隨機選擇一個。 如果你的哈希值比權重的總和大3或4倍,那么你的復雜性將非常好:O(1)用於檢索隨機樣本,O(| AB |)用於修改權重。

另一種選擇,因為只有一小部分重量發生變化,就是將重量分成兩部分 - 固定部分和變化部分。 然后,您只需要擔心更改部件的更改,以及更改部件的總重量與未更改部件的總重量之間的差異。 然后對於固定部分,您的哈希變為一個簡單的數字數組:1出現w1次,2出現w2次等等,並且選擇隨機固定元素只是選擇一個隨機數。

更改值時更新標准化因子非常簡單。 這可能暗示了一種算法。

w_sum = w_sum_old - w_i_old + w_i_new;

如果將p_i作為計算屬性p_i = w_i / w_sum,則應避免重新計算整個p_i數組,但需要在每次需要時計算p_i。 但是,您可以在不重新計算總和的情況下更新許多統計屬性

expected_something = (something_1 * w_1 + something_2 * w_2 + ...) / w_sum;

通過一些代數,您可以通過減去舊權重的貢獻來更新expected_something,並使用新權重添加貢獻,根據需要乘以和除以標准化因子。

如果您在采樣期間跟蹤哪些結果是樣本的一部分,則可以傳播概率如何更新為生成的樣本。 這是否可以讓您更新而不是重新計算與樣本相關的值? 我認為位圖可以提供一種有效的方法來存儲用於構建樣本的結果的索引。

將概率與總和一起存儲的一種方法是從所有概率開始。 在接下來的N / 2個位置,您可以存儲貨幣對的總和。 在那之后,總和所在的N / 4總和可以顯然在O(1)時間內計算。 這種數據結構有點堆,但是顛倒了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM