Algorithm 从长度未知的流中均匀分布的样本

Algorithm 从长度未知的流中均匀分布的样本,algorithm,random,Algorithm,Random,我想从一个N项目流中抽取K个项目,一次一个。直到最后一项出现,我才知道N有多大,我希望空间消耗取决于K而不是N 到目前为止,我已经描述了一个水库取样问题。但主要的问题是,我希望样本“均匀分布”,或者至少比水库采样管理的更均匀分布。这是模糊的;一种形式化的说法是,样本索引是a,但我并不特别关注这一点 我也希望这个过程是随机的,每个可能的样本出现的概率都不是零,但我也不是特别喜欢这个 我的直觉是,这是一个可行的问题,我想象的算法优先从水库的“最高密度”部分滴下样本,以便为来自流入河流的样本留出空间。

我想从一个
N
项目流中抽取
K
个项目,一次一个。直到最后一项出现,我才知道
N
有多大,我希望空间消耗取决于
K
而不是
N

到目前为止,我已经描述了一个水库取样问题。但主要的问题是,我希望样本“均匀分布”,或者至少比水库采样管理的更均匀分布。这是模糊的;一种形式化的说法是,样本索引是a,但我并不特别关注这一点

我也希望这个过程是随机的,每个可能的样本出现的概率都不是零,但我也不是特别喜欢这个

我的直觉是,这是一个可行的问题,我想象的算法优先从水库的“最高密度”部分滴下样本,以便为来自流入河流的样本留出空间。这似乎也是一个很常见的问题,应该有人在上面写一篇论文,但谷歌搜索“等间距”、“水库”、“准陆地”、“采样”的组合并没有让我有所收获

编辑#1:举个例子可能会有所帮助

例子 假设
K=3
,我得到项目
0、1、2、3、4、5、

在3项之后,示例将是
[0,1,2]
,空格为
{1}

在6个项目之后,我希望最频繁地获得
[0,2,4]
,其空格为
{2}
,但通常获得
[0,3,5]
[0,2,4]
等示例,其空格为
{2,3}
也会很好

在9个项目之后,我希望最频繁地获得
[0,4,8]
,其空格为
{4}
,但通常获得
[0,4,7]
之类的样本,其空格为
{4,3}
,也会很好

编辑#2:我在这里学到了一个关于在请求答案时提供大量上下文的教训。David和Matt的答案很有希望,但如果有人看到了这一点,并有了一个完美的解决方案,这里有更多的信息:

上下文
我有数百个通过GPU传输的低分辨率视频。每个流最多有10000帧长,根据应用程序的不同,我想从每个流中抽取10到1000帧。一旦一个流完成了,我得到了一个样本,它被用来训练一个机器学习算法,然后被扔掉。另一条小溪在它的地方开始流动。GPU的内存为10G,一组“好”的存储库在当前应用程序中占用了几GB,在未来的应用程序中可能接近整个内存

如果空间不是额外的,我会使用统一随机库算法通过一些常数因子进行过采样(例如,如果需要k个项目,则采样10k),并记住每个采样项目出现的索引。最后,使用动态规划选择k个索引,以最大化(例如)连续选择的索引之间的间隔日志的总和。

这里有一个不需要太多额外内存的算法。希望它能满足您的质量要求

高级思想是将输入划分为k个段,并从每个段中随机均匀地选择一个元素。考虑到内存的限制,我们不能让片段像我们希望的那样均匀,但它们将在两倍以内

该算法的简单版本(使用2k个存储槽,可能返回k到2k之间任何大小的样本)从读取前k个元素开始,然后依次进行。在r轮(从零开始计数)中,我们读取k 2r元素,使用标准库算法从2r的每个片段中选择一个随机样本。在每轮结束时,我们将这些样品添加到现有储层中,并执行以下压缩步骤。对于每对连续图元,请均匀随机选择一个以保留和丢弃另一个图元

该算法的复杂版本使用k个时隙,并通过将循环采样步骤与压缩交错来返回大小为k的样本。我将演示它,而不是写一个正式的描述,因为我认为这样更容易理解

设k=8。我们在读取了32个元素后进行拾取。我使用符号
[a-b]
表示索引介于
a
b
之间的随机元素。水库看起来像这样:

[0-3] [4-7] [8-11] [12-15] [16-19] [20-23] [24-27] [28-31]
在处理下一个元素(
32
)之前,我们必须腾出空间。这意味着将
[0-3]
[4-7]
合并为
[0-7]

[0-7] [32] [8-11] [12-15] [16-19] [20-23] [24-27] [28-31]
我们将接下来的几个元素合并到
[32]

[0-7] [32-39] [8-11] [12-15] [16-19] [20-23] [24-27] [28-31]
元素
40
需要另一次合并,这次是
[16-19]
[20-23]
。一般来说,我们以低差异顺序进行合并

[0-7] [32-39] [8-11] [12-15] [16-23] [40] [24-27] [28-31]
继续

[0-7] [32-39] [8-11] [12-15] [16-23] [40-47] [24-27] [28-31]
在回合结束时,水库看起来是这样的

[0-7] [32-39] [8-15] [48-55] [16-23] [40-47] [24-31] [56-63]
我们使用FFT中的标准技术撤销新样本的蝴蝶排列,并将它们移动到最后

[0-7] [8-15] [16-23] [24-31] [32-39] [40-47] [48-55] [56-63]

然后我们开始下一轮。

也许进行储层取样的最简单方法是将随机分数与每个样本关联,然后使用堆来记住分数最高的k个样本

这对应于对白噪声应用阈值操作,其中选择阈值以允许正确数量的样本。每个样本都有相同的机会被包括在输出集中,就好像k个样本被统一选择一样

但是,如果对蓝色噪波而不是白色噪波进行采样以生成分数,则应用阈值操作将生成低差异序列,并且输出集中的采样间隔将更均匀。出现这种效果的原因是,虽然白噪声样本都是独立的,但蓝噪声样本在时间上是反相关的

此技术用于创建令人愉悦的半色调图案(google Bl)