理想情况下,我希望以下内容不会多次从硬盘读取数据。数据很大,内存不能同时保存所有数据。
x[t]
。数字流包含N
个元素。x
个m
个柱子的直方图。N/m
的某个阈值百分比内。这是因为如果我们在m个bin中均匀分布N
个元素,则每个bin应该包含大约N/m
个元素。目前的解决方案:
import numpy as np
def test_data(size):
x = np.random.normal(0, 0.5, size // 2)
x = np.hstack([x, np.random.normal(4, 1, size // 2)])
return x
def bin_edge_as_index(n_bin, fine_hist, fine_n_bin, data_size):
cum_sum = np.cumsum(fine_hist)
bin_id = np.empty((n_bin + 1), dtype=int)
count_per_bin = data_size * 1.0 / n_bin
for i in range(1, n_bin):
bin_id[i] = np.argmax(cum_sum > count_per_bin * i)
bin_id[0] = 0
bin_id[n_bin] = fine_n_bin
return bin_id
def get_bin_count(bin_edge, data):
n_bin = bin_edge.shape[0] - 1
result = np.zeros((n_bin), dtype=int)
for i in range(n_bin):
cmp0 = (bin_edge[i] <= data)
cmp1 = (data < bin_edge[i + 1])
result[i] = np.sum(cmp0 & cmp1)
return result
# Test Setting
test_size = 10000
n_bin = 6
fine_n_bin = 2000 # use a big number and hope it works
# Test Data
x = test_data(test_size)
# Fine Histogram
fine_hist, fine_bin_edge = np.histogram(x, fine_n_bin)
# Index of the bins of the fine histogram that contains
# the required bin edges (e_1, e_2, ... e_n)
bin_id = bin_edge_as_index(
n_bin, fine_hist, fine_n_bin, test_size)
# Find the bin edges
bin_edge = fine_bin_edge[bin_id]
print("bin_edges:")
print(bin_edge)
# Check
bin_count = get_bin_count(bin_edge, x)
print("bin_counts:")
print(bin_count)
print("ideal count per bin:")
print(test_size * 1.0 / n_bin)
节目输出:
bin_edges:
[-1.86507282 -0.22751473 0.2085489 1.30798591 3.57180559 4.40218207
7.41287669]
bin_counts:
[1656 1675 1668 1663 1660 1677]
ideal count per bin:
1666.6666666666667
问题:
我无法指定阈值s,并且预计bin计数与每个bin的理想计数最多不同s%。
答案 0 :(得分:1)
Iff 您可以假设您的数据是随机的定义的分布(即:按顺序获取任何非平凡的数据百分比将“草图”与整个数据相同的分布,只有更粗略的精度),我想有很多选择:
在一些过采样直方图中读取部分数据。在此基础上,选择bin边缘的近似你现在的方式(如你的问题中所解释的),然后统一对这些bin进行过采样,然后将另一块数据读入新的bin中,等等上。如果您有足够的数据,那么以10%10%的块处理它们将允许10次迭代,以便在一次通过中改善您的箱结构。
从多个bin开始并累积一些(不是全部)数据。查看它们,如果有一个bin_width*count
不成比例地高于邻居(也许这是精确/错误可能发挥作用的地方),将该bin分成两部分,并启发式地将旧bin计数分配到新创建的bin中(一种可能的启发式方法 - 与邻居的数量成正比)。最后,你应该以一个可接受的错误控制某个部门,从中排序你的发行版。
当然,以上只是方法的想法,不能保证它们的工作状态。
答案 1 :(得分:1)
假设分布不是非常歪斜(例如在1.0000001和1.0000002之间的10000个值以及在9.0000001和9.0000002之间的10000个其他值),您可以按照以下步骤进行操作。
计算具有足够分辨率的直方图,例如K
个分箱,涵盖整个范围(希望事先知道)。这将对数据进行一次传递。
然后计算累积直方图,当你去的时候,确定m+1
分位数边缘(累积计数交叉为N/m
的倍数)。
您将获得的准确度取决于原始直方图的bin中的最大元素数。
对于N
个元素,使用K
个二进制位的直方图并假设一些&#34;非均匀性因子&#34; (等于合理分布的几个单位),最大误差为f.N/K
。
如果您愿意,可以通过考虑m+1
辅助直方图来提高准确度,辅助直方图仅累积落入全局直方图的分位数区间的值。然后,您可以将分位数细化为这些辅助直方图的分辨率。
这将花费您额外的通行费,但错误将减少到f.N/(K.K')
,仅使用K
然后m.K'
直方图空间,而不是K.K'
。