维护一个对象容器,该容器按该对象的成员与其邻居的成员之间的差异排序

时间:2011-07-27 16:53:53

标签: c++ algorithm boost time-complexity

我正在努力实现直方图,其中一个关键点是直方图箱的快速合并。因为我没有关于直方图近似的数据集的先验知识,所以我需要提出一种方法,在我超过最大数量的垃圾箱之后快速合并相邻的垃圾箱。

因此,作为一个例子,如果您使用五个直方图箱来近似数据流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之间的差异,然后对那些值进行排序

有没有办法对这些值进行排序,同时保持列表的完整性,而不引入新的容器(例如差异/迭代器键/值对的多重映射)?

维护此列表是我目前对复杂性问题的近似最优解决方案的想法,因为它只需要在合并时进行更改,并且仅在添加新值时才会进行合并。

任何想法或见解都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

我看到的主要问题是你创建了一个系统,你不断重新计算直方图,最坏的情况是每个新元素。

这样的事情:

  1. 对于N个bin,Bin min 到Bin max ,将它们分配给输入的初始值
  2. 对于每个新的数字X,如果X是&lt; Bin min 设置Bin min = X否则如果X&gt; Bin max 设置Bin max = X
  3. 如果您更改了2中的边界,请设置每个bin的值,使Bin L =(Bin max - Bin min )/ N * L,其中L是bin序数
  4. 将X添加到最接近X的bin。
  5. 这是卫生巾的后面,所以我确定某处有一个错误。这个想法只是当一个值落在它之外时才“重构”直方图,所以你需要做的就是将X添加到与它最匹配的bin中。我相信这应该导致非常相似的直方图,如果不相等。第1步是初始化,步骤2-4是循环,如果不清楚的话。

答案 1 :(得分:0)

将此作为答案发布:

看看这个问题的答案:Online k-means clustering。如果我正确理解你的问题,那就是你要找的东西,那里最初的k猜测是你的第一个k值。

如果您对bin中心进行了排序,则可以对列表进行二分查找,最接近的值可以是前一个值或后一个值,总体复杂度为O(n*log(m)),其中m为箱数和n是数据量。