将float数组划分为类似的段(聚类)

ale*_*dro 10 c++ java algorithm cluster-analysis data-partitioning

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

[1.91, 2.87, 3.61, 10.91, 11.91, 12.82, 100.73, 100.71, 101.89, 200]
Run Code Online (Sandbox Code Playgroud)

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

[[1.91, 2.87, 3.61] , [10.91, 11.91, 12.82] , [100.73, 100.71, 101.89] , [200]]
Run Code Online (Sandbox Code Playgroud)

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

我必须为几个数组找到这种段,我不知道分区大小应该是多少.我试图通过使用层次聚类(Agglomerative)来实现它 ,它为我提供了令人满意的结果.然而,问题是,我被建议不要将聚类算法用于一维问题,因为它们没有理论上的理由(因为它们用于多维数据).

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

我找到了另一个建议,而不是聚类,即自然中断优化.但是,这也需要声明分区号,如K-means(右?).

这很混乱(特别是因为我必须在几个阵列上执行这种分段,并且不可能知道最佳分区号).

有什么方法可以找到分区(因此我们可以通过一些理论上的合理性来减少分区内的差异并最大化分区之间的差异)?

任何指向文章/论文的指针(如果可用的C/C++/Java实现)都有一些理论上的理由对我很有用.

Jer*_*fin 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;
}
Run Code Online (Sandbox Code Playgroud)

结果:

1.91    2.87    3.61
10.91   11.91   12.82
100.71  100.73  101.89
200
Run Code Online (Sandbox Code Playgroud)