10

我有一个这样的浮点数组:

[1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200]

现在,我想像这样对数组进行分区:

[[1.91, 2.87, 3.61] , [10.91, 11.91, 12.82] , [100.73, 100.71, 101.89] , [200]]

// [200] 将被视为异常值,因为集群支持较少

我必须为几个数组找到这种段,我不知道分区大小应该是多少。我尝试通过使用 层次聚类(凝聚)来做到这一点,它给了我令人满意的结果。但是,问题是,有人建议我不要将聚类算法用于一维问题,因为它们没有理论上的理由(因为它们适用于多维数据)。

我花了很多时间寻找解决方案。但是,建议似乎完全不同,例如:thisthis VS。这个这个这个

我发现了另一个建议,而不是聚类,即自然休息优化。但是,这也需要像 K-means 一样声明分区号(对吗?)。

这很令人困惑(特别是因为我必须在几个数组上执行那种分段并且不可能知道最佳分区号)。

有什么方法可以找到分区(因此我们可以减少分区内的方差并最大化分区之间的方差)并具有一些理论依据?

任何指向文章/论文的指针(如果可用的 C/C++/Java 实现)具有一些理论依据将对我非常有帮助。

4

2 回答 2

10

我想我会对数据进行排序(如果还没有的话),然后取相邻的差异。将差异除以较小的数字,得到百分比变化。设置一个阈值,当变化超过该阈值时,启动一个新的“集群”。

编辑:C++ 中的快速演示代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
#include <functional>

int main() {
    std::vector<double> data{ 
        1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200 
    };

    // sort the input data
    std::sort(data.begin(), data.end());

    // find the difference between each number and its predecessor
    std::vector<double> diffs;
    std::adjacent_difference(data.begin(), data.end(), std::back_inserter(diffs));

    // convert differences to percentage changes
    std::transform(diffs.begin(), diffs.end(), data.begin(), diffs.begin(),
        std::divides<double>());

    // print out the results
    for (int i = 0; i < data.size(); i++) {

        // if a difference exceeds 40%, start a new group:
        if (diffs[i] > 0.4)
            std::cout << "\n";

        // print out an item:
        std::cout << data[i] << "\t";
    }

    return 0;
}

结果:

1.91    2.87    3.61
10.91   11.91   12.82
100.71  100.73  101.89
200
于 2013-07-05T01:57:34.017 回答
3

聚类通常假设多维数据。

如果您有一维数据,请对其进行排序,然后使用核密度估计,或者只扫描最大的间隙。

在一维中,问题变得容易得多,因为可以对数据进行排序。如果您使用聚类算法,很遗憾它不会利用这一点,因此请改用一维方法!

考虑找出一维数据中的最大差距。这很简单:排序(n log n,但实际上尽可能快),然后查看两个相邻值的最大差异。

现在尝试在二维中定义“最大间隙”,以及一个有效的算法来定位它......

于 2013-07-05T07:44:13.090 回答