Raf*_*ini 17 algorithm statistics histogram data-structures
是否有已知的算法+数据结构来维持动态直方图?
想象一下,我有一个数据流(x_1,w_1),(x_2,w_2),...其中x_t是双精度数,代表一些测量变量,w_t是相关权重.
我可以做明显的(伪python代码):
x0,xN = 0, 10
numbins = 100
hist = [(x0 + i * delta , 0) for i in xrange(numbins)]
def updateHistogram(x, w):
k = lookup(x, hist) #find the adequated bin where to put x
hist[k][1] += 1
Run Code Online (Sandbox Code Playgroud)
但是当我有连续的数据流时,我遇到了一些问题.我手头没有完整的数据集,我必须在数据收集之间检查直方图.而且我没有期望:
所以我想动态定义二进制文件.我可以做愚蠢的事情:
for x in data_stream:
data.append(x)
hist = make_histogram(data)
Run Code Online (Sandbox Code Playgroud)
但我想这会很快变慢......
如果所有权重等于我认为的事情之一就是将数据存储在排序数组中并以保持数组排序的方式插入新数据.这样我可以:
data = sortedarray();
for x in data_stream:
data.insert(x)
bins = [ data[int(i * data.size()/numbins)] for i in xrange(numbins)]
Run Code Online (Sandbox Code Playgroud)
并且每个bin中的计数等于所有bin的data.size()/ numbins.
我想不出在这方面包括权重的方法......有没有人有建议?(关于这样做的c ++库的知识也会受到欢迎).
编辑:(对于要求的澄清)
x_t是浮点数.要计算直方图,我必须将x所属的连续范围除以多个区间.所以我将有一个数字序列bin [0],bin [1]等...所以我必须确定我做什么bin [i] <x <bin [i + 1].
这是您在预先获得所有数据时通常进行直方图的方法.然后,您将知道极限(x)和min(x)的极限,并且很容易确定足够的箱.例如,你可以让它们在min(x)和max(x)之间等间隔.
如果您事先不知道范围,则无法确定容器.你可以收到一个不属于任何垃圾箱的x.或者你可以使用许多空箱,因为你选择了太大的范围来制作垃圾箱.
csg*_*pie 14
如何确定垃圾箱的数量
确定直方图中的箱数有许多规则.对于你的问题,我会选择Scott的选择:
bin_width = 3.5*sd*n^{-1/3}
Run Code Online (Sandbox Code Playgroud)
其中sd是标准偏差,n是数据点的数量.至关重要的是,您可以使用在线算法来计算标准偏差.箱数k由下式给出:
k = ceil((max(x) - min(x))/bin_width)
Run Code Online (Sandbox Code Playgroud)
存储数据
假设我们已观察到N个数据点.然后是标准差的置信区间,
Lower limit: sd*sqrt((N-1)/CHIINV((alpha/2), N-1))
Upper limit: sd*sqrt((N-1)/CHIINV(1-(alpha/2), N-1))
Run Code Online (Sandbox Code Playgroud)
其中CHIINV是卡方分布的值.当N = 1000时,sd的CI为:
(0.96*sd, 1.05*sd)
Run Code Online (Sandbox Code Playgroud)
所以bin宽度为95%CI:
(3.5*0.96*sd*1000^{-1/3}, 3.5*1.05*sd*1000^{-1/3})
(0.336*sd, 0.3675*sd)
Run Code Online (Sandbox Code Playgroud)
您可以获得类似垃圾箱的数量.
算法
评论
小智 5
听起来好像您要实现以下抽象数据类型。
insert(x, w): add item x to the collection with weight x
select(p): return the item greater than a p weighted fraction of the items
Run Code Online (Sandbox Code Playgroud)
例如,select(0)返回最小值,select(0.5)返回加权中位数,然后select(1)返回最大值。
我将以两种方式之一实现此ADT。如果很少进行选择,则将数据放入数组中,并使用线性时间选择算法进行O(1)次插入和O(n)次选择。如果选择频繁,我将使用二进制搜索树,其中每个节点将总权重存储在其子树中。例如,之后
insert(2, 10)
insert(1, 5)
insert(3, 100)
insert(4, 20)
Run Code Online (Sandbox Code Playgroud)
那棵树可能看起来像
2 (135)
/ \
/ \
1 (5) 4 (120)
/
/
3 (100)
Run Code Online (Sandbox Code Playgroud)
现在,找到加权中值,乘以135通过0.5并获得67.5如所期望的“指标”。从根开始2,我们发现5小于67.5,因此该项不在左子树中,我们减去5以获得62.5树的其余部分的索引。由于135 - 120 = 15小于62.5,中位数不是2。我们15从中减去62.5得到47.5并下降到4。在4,我们发现100大于47.5,3中位数也是如此。
假设树是平衡的,则insert和的运行时间select为O(log n)。如果我是从头开始实现的,那么我可能会选择一个八卦树。
| 归档时间: |
|
| 查看次数: |
6987 次 |
| 最近记录: |