我正在努力实现直方图,其中一个关键点是直方图箱的快速合并。因为我没有关于直方图近似的数据集的先验知识,所以我需要提出一种方法,在我超过最大数量的垃圾箱之后快速合并相邻的垃圾箱。
因此,作为一个例子,如果您使用五个直方图箱来近似数据流23,19,10,16,36,2,9,32,30,45,那么您将读入前五个元素,获得:
(23,1),(19,1),(10,1),(16,1),(36,1)
添加bin(2,1)会导致问题,因为我们已经超过了最大bin数。因此,我们添加(2,1)并合并两个最接近的二进制位 - (16,1)和(19,1) - 得到一个新的bin(17.5,2)替换这两个。
对于直方图的其余部分重复此方法,我们得到了最终输出:
(2,1),(9.5,2),(19.33,3),(32.67,3),(45,1)。
在不考虑复杂性问题的情况下实现这一点是微不足道的。但是,我真的很关心为大数据集优化它,因为我的“琐碎”实现最终需要15秒才能在100,000高斯分布值的流上运行。
我目前的想法是使用boost :: multi_index来跟踪我的HistogramBin结构,定义为:
struct HistogramBin
{
double bin;
unsigned long count;
bool isNull;
HistogramBin(double x, bool n = false)
: bin(x), count(1), isNull(n) {}
bool operator<(const HistogramBin &other) const
{ return (bin < other.bin); }
// Merges other with this histogram bin
// E.g., if you have (2.0,1) and (3.0,2), you'd merge them into (2.67,3)
void merge(const HistogramBin &other)
{
unsigned long old_count = count;
count += other.count;
bin = (bin*old_count + other.bin*other.count)/count;
}
// Gets the difference between two histogram bins
const double getDifference(const HistogramBin &other) const
{ return (double)abs(bin - other.bin); }
};
因此,multi_index将使用ordered_unique&lt;&gt;对HistogramBin :: bin进行排序。
现在,这并不能解决因相邻垃圾箱之间的差异而对垃圾箱进行排序的问题。通过HistogramBin :: bin索引为我们提供了一个有序的HistogramBin对象列表,但接下来的步骤是计算当前bin和下一个bin之间的差异,然后对那些值进行排序
有没有办法对这些值进行排序,同时保持列表的完整性,而不引入新的容器(例如差异/迭代器键/值对的多重映射)?
维护此列表是我目前对复杂性问题的近似最优解决方案的想法,因为它只需要在合并时进行更改,并且仅在添加新值时才会进行合并。
任何想法或见解都将受到赞赏。
答案 0 :(得分:1)
我看到的主要问题是你创建了一个系统,你不断重新计算直方图,最坏的情况是每个新元素。
这样的事情:
这是卫生巾的后面,所以我确定某处有一个错误。这个想法只是当一个值落在它之外时才“重构”直方图,所以你需要做的就是将X添加到与它最匹配的bin中。我相信这应该导致非常相似的直方图,如果不相等。第1步是初始化,步骤2-4是循环,如果不清楚的话。
答案 1 :(得分:0)
将此作为答案发布:
看看这个问题的答案:Online k-means clustering。如果我正确理解你的问题,那就是你要找的东西,那里最初的k猜测是你的第一个k值。
如果您对bin中心进行了排序,则可以对列表进行二分查找,最接近的值可以是前一个值或后一个值,总体复杂度为O(n*log(m))
,其中m
为箱数和n
是数据量。