WAL*_*ISK 1 ruby random probability
我有 3 个分类稀有度,概率是这样的
class S has 10% probability
class A has 30% probability
class B has 60% probability
Run Code Online (Sandbox Code Playgroud)
所以我这样编码
class S has 10% probability
class A has 30% probability
class B has 60% probability
Run Code Online (Sandbox Code Playgroud)
我的客人的结果是非常正确的(cmiiw)
B
A
B
B
S
B
A
S
B
A
B
Run Code Online (Sandbox Code Playgroud)
但当我应该添加更多类别并将 S 类别概率更改为 1% 时,我变得很困惑
池现在变成
class S has 1% probability
class A has 29% probability
class B has 30% probability
class C has 40% probability
Run Code Online (Sandbox Code Playgroud)
我不确定我pool之前应该创建类似池的变量,因为 1% 是 1/10 不是整数。
急需帮助,谢谢!
考虑使用免费软件 gem aliastable。它\xe2\x80\x99 是 AJ Walker 于 1974 年发布的别名方法的 Ruby 实现。注意:我是作者。
\n更新:根据评论中的反馈(感谢@engineersmnky!),gem 现在可以优雅地处理离散均匀分布\xe2\x80\x94,其中所有概率都相等\xe2\x80\x94,基于下面描述的情况 1。它还已更新为使用惰性枚举生成值。
\n当分布包含不等概率时,别名方法需要 O(n) 时间来创建包含 n 个结果的表,然后生成每个值需要 O(1) 时间。相比之下,从概率质量函数构建 CDF,然后对值进行二分搜索将分别花费 O(n) 和 O(log n) 时间。
\n这个小演示展示了如何使用 gem:
\nrequire \'aliastable\'\n\nvalues = %w(S A B C)\nprobs = [1r/100, 29r/100, 3r/10, 2r/5] # r => Rational\nmy_distribution = AliasTable.new(values, probs)\n\np my_distribution.take(1_000_000).tally\nRun Code Online (Sandbox Code Playgroud)\n产生如下结果
\n{"C"=>400361, "B"=>300121, "A"=>289636, "S"=>9882}\nRun Code Online (Sandbox Code Playgroud)\n当尝试从一组离散的n 个项目生成值时,有两种情况可以在恒定时间内完成这项工作:
\nvalues[rand(n)]。别名方法构建一个包含三行、primary、alias、primary_probability和n列的表。每个结果都分配给一列,作为该列\xe2\x80\x99sprimary值,其概率输入为primary_probability。该alias列的 被初始化为nil。然后可以根据与主要相关的概率相对于平均概率1/n将该列分类为属于三个集合之一:
primary_probability < 1/nprimary_probability > 1/nprimary_probability = 1/n请注意,赤字集中 \xe2\x80\x9cmissing\xe2\x80\x9d 概率的总量恰好等于盈余集中 \xe2\x80\x9cexcess\xe2\x80\x9d 概率的总量,因此该表结构通过从盈余列之一窃取概率使赤字列之一达到平价来平衡账簿。primary被窃取的列的值将被添加为当前alias赤字列。条件概率用于计算主值拥有该列概率的比例并进行primary_probability相应调整。然后将该列迁移到奇偶校验集。此外,被盗概率的数量必须从选定的盈余列中递减,这可能使其仍然具有盈余,或者可能将其分类更改为赤字或平价。如果分类发生更改,请将其迁移到适当的集合。
重复此过程,直到所有列都在奇偶校验集中。表构建算法保证在少于n次迭代内终止,因为每次迭代都会将一个赤字列(可能还有一个剩余列)迁移到奇偶校验集。
\n一旦表构建完成,我们就有n列,每一列都有相等的总概率。每列都有一个主值,或者一个主值和一个别名,以及在我们进入该列的情况下选择主值的条件概率。则生成算法为:
\n编码逻辑为:
\ncolumn = rand(n)\nif rand < primary_probability[column]\n return primary[column]\nelse\n return alias[column]\nend\nRun Code Online (Sandbox Code Playgroud)\n由于这两个步骤都是恒定时间,因此生成结果的总时间也是恒定的。
\n