#distribution #random #sampling

histogram-sampler

从由直方图给出的分布中进行抽样

9个不稳定版本

使用旧的Rust 2015

0.5.0 2021年6月19日
0.4.0 2019年7月10日
0.3.0 2018年12月4日
0.2.1 2018年12月4日
0.1.3 2018年3月16日

#363 in 模拟

每月46次下载
2 crates 中使用

MIT/Apache

20KB
160 代码行

histogram-sampler

Crates.io Documentation Build Status

从由直方图近似的数据分布中进行抽样。

这个crate解决了一个非常具体的问题,可能不是你想要的。最好通过视觉来解释。想象一下这样一个直方图

 0 |---------| 100
10 |-------| 80
20 |---| 40
30 |--| 30
40 |-| 20
50 |-| 18
60 || 10
70 || 7

现在想象一下它是通过取一系列值,计算每个值的数量,将这些计数四舍五入到最接近的十,然后绘制结果直方图来创建的。这个crate允许你使用这样的数据,并生成一个生成器,该生成器将生成一个新的、无限的值序列,其值的分布与产生直方图的序列相匹配。

这时,你可能想知道:我为什么想这样呢?

事实上,你可以用这种方式模拟很多有用的东西。例如,以类似lobste.rs(我们实际上有数据)网站上文章的投票和评论分布为例。想象一下,你想制作一个工作负载生成器,来模拟此类网站将看到的工作负载。特别是,你想要确保一些文章比其他文章更受欢迎,一些评论比其他评论更受欢迎等。想想这些数据可能看起来像什么……许多帖子将有0-10个赞,一些将有10-20个,更少的将有20-30个,等等。评论也是这样。或者评论的赞。或者每个评论的子评论数。或者用户提交的故事。你明白了。所有这些都可以以上述形式表示,其中抽样值将是故事/评论/用户ID!

让我们用一个基于一些真实数据的例子来展示。

// original histogram data
let stories_per_votecount = vec![
    (0, 16724), (10, 16393), (20, 4601), (30, 1707),
    (40, 680), (50, 281), (60, 128), (70, 60), (80, 35),
    (90, 16), (100, 4), (110, 4), (120, 10), (130, 1),
    (140, 2), (160, 1), (210, 1), (250, 1), (290, 1),
];

let mut rng = rand::thread_rng();
let vote_sampler = Sampler::from_bins(stories_per_votecount, 10 /* bin width */);
for _ in 0.. {
    use rand::distributions::Distribution;
    println!("vote for {}", vote_sampler.sample(&mut rng));
}

如果您运行那段代码(目前它会无限运行),您会看到一系列对虚构故事ID的投票,这些故事ID位于[0, 40650)范围内(因为原始直方图中就有这么多故事)。如果您在约370k次投票后收集每个故事的投票数直方图,那么这个直方图将几乎完全像原始输入直方图!如果您在更早或更晚的时候采样,则不会如此,因为总投票数会更少/更多,这将有效地将数据推向较低的或较高的桶。但是,故事ID之间的分布将保持不变,因此您可以继续使用这种方法来模拟持续进行的工作负载。

小桶大小偏差

当您的桶大小很小([0, 5)的值,因为任何更大的值都会四舍五入到10。不幸的是,这也意味着有相对较高的可能性无意中将一个本应位于第一个桶的值推入第二个桶。只需将这个值比预期多一次或两次即可。事实上,这实际上是相当可能的。这种净效应是,第一个桶(再次强调,如果桶宽度小)可能值太少(通常少约5个百分点),而第二个桶可能值太多(同样约5个百分点)。

依赖关系

~305KB