C++ c++;概率频繁变化的离散分布抽样

C++ c++;概率频繁变化的离散分布抽样,c++,statistics,distribution,probability,sampling,C++,Statistics,Distribution,Probability,Sampling,问题:我需要从由某些权重构成的离散分布中取样,例如{w1,w2,w3,…},然后是概率分布{p1,p2,p3,…},其中pi=wi/(w1+w2+…) 一些wi的变化非常频繁,但在所有wi中只有很低的比例。但分布本身因此必须在每次发生时重新规范化,因此我认为Alias方法无法有效工作,因为每次都需要从头开始构建整个分布 我目前正在考虑的方法是二叉树(堆方法),其中所有wi都保存在最低级别,然后在更高级别保存每两个wi的总和,以此类推。它们的总和将处于最高水平,这也是一个归一化常数。因此,为了在w

问题:我需要从由某些权重构成的离散分布中取样,例如{w1,w2,w3,…},然后是概率分布{p1,p2,p3,…},其中pi=wi/(w1+w2+…)

一些wi的变化非常频繁,但在所有wi中只有很低的比例。但分布本身因此必须在每次发生时重新规范化,因此我认为Alias方法无法有效工作,因为每次都需要从头开始构建整个分布

我目前正在考虑的方法是二叉树(堆方法),其中所有wi都保存在最低级别,然后在更高级别保存每两个wi的总和,以此类推。它们的总和将处于最高水平,这也是一个归一化常数。因此,为了在wi更改后更新树,需要进行日志(n)更改,以及从分发中获取相同数量的样本

问题:

问题1。你对如何更快地实现这一目标有更好的想法吗? 问题2。最重要的部分:我正在寻找一个已经做到这一点的图书馆

说明:几年前我自己就这样做了,通过在向量中构建堆结构,但从那以后我学到了很多东西,包括发现库(:)和容器,如map。。。现在,我需要用更高的功能重写该代码,我希望这次能够做到:

S.Q2.1有一个很好的方法来让C++地图不是按索引排序和搜索,而是通过它的元素的累积和(这是我们如何采样,对……)进行排序。(这是我目前的理论,我想这样做,但不一定要这样做……)

问题2.2也许有更好的方法可以做到这一点?我相信这个问题是如此频繁,我非常惊讶,我找不到某种图书馆可以为我做这件事

非常感谢,我很抱歉,如果有人以其他形式问我这个问题,请告诉我,但我花了很长时间寻找

-z

编辑:有可能我也需要删除或添加元素,但我认为我可以避免,如果这会造成巨大的差异,从而只留下更改权重值


Edt2:一般来说,权重是Reals,我必须想,如果我可以让它们成为整数……< /P> < P>我实际上会使用一个字符串的哈希集(不要记住C++容器,但是你可能需要实现自己的字符串)。为每个i放置wi元素,值为“w1_1”、“w1_2”,。。。全部通过“w1_U1;[w1]”(即,以“w1_U1;”开头的w1元素)

需要采样时,使用均匀分布随机拾取元素。如果选择了w5,则表示选择了元素5。由于散列中元素的数量,这将为您提供所需的分布

现在,当wi从A变为B时,只需将B-A元素添加到散列中(如果B>A),或者删除wi的最后一个A-B元素(如果A>B)

在这种情况下,添加新元素和删除旧元素非常简单

显然,问题在于“随机选取一个元素”。如果你的散列是一个封闭的散列,你可以随机选取一个数组单元格,如果它是空的,只需再次随机选取一个即可。如果将哈希值保持为权重总和的3到4倍,那么您的复杂性将非常好:O(1)用于检索随机样本,O(| a-B |)用于修改权重


另一种选择是,因为只有一小部分权重发生变化,所以将权重分为两部分——固定部分和变化部分。然后,您只需要担心更改的零件的更改,以及更改零件的总重量与未更改零件的总重量之间的差异。然后,对于固定部分,散列变成了一个简单的数字数组: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;
通过一点代数,你可以用旧的权重减去贡献,然后用新的权重加上贡献,再根据需要用标准化因子乘和除,来更新期望的值

如果您在采样期间跟踪哪些结果是样本的一部分,那么就有可能将概率更新的方式传播到生成的样本中。这是否使您能够更新而不是重新计算与样本相关的值?我认为位图可以提供一种有效的方法来存储用于构建样本的结果的索引


存储概率和总和的一种方法是从所有概率开始。在接下来的N/2位置中,存储成对的和。在此之后,显然可以在O(1)时间内计算出求和所在的对的N/4和。这种数据结构有点像堆,但却是颠倒的

您假定权重是整数。根据我对问题的理解,权重是真实的。罗宾可能会说,天哪,蝙蝠侠,你说得对!谢谢各位,是的,这些数字是真实的,我不认为我能把它们近似成整数,因为还有很多小概率事件仍然可能发生。第二个建议很好,但非常混乱,即在某个时候我必须重新制作整个列表,等等。。我认为二叉树仍然是最好的,但是没有人给我一个简单的方法来实现它/是的,这是显而易见的,但是谢谢。问题是要对分布进行采样——为此,您还需要更新日志(n)和