如何使用微笑库的CLARANS方法将数据与自定义距离矩阵聚类

时间:2019-05-29 12:07:40

标签: java cluster-analysis k-means distance-matrix smile

我想用自定义距离矩阵而不是内置算法(即欧几里得)对数据进行聚类。而且似乎没有明确的方法。

我尝试将一些代码添加到Smile项目的演示中。还尝试在我的项目中进行测试,这是其中的一部分代码:

        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = vrpJsonFromFile.readLine()) != null) {
            sb.append(line).append("\n");
        }
        JSONArray jsonArray = new JSONObject(sb.toString()).getJSONArray("services");
        Double[][] data = new Double[jsonArray.length()][2];
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject address = jsonArray.getJSONObject(i).getJSONObject("address");
            data[i][0] = Double.parseDouble(address.getString("lon"));
            data[i][1] = Double.parseDouble(address.getString("lat"));
        }

        // here
        Distance<Double[]> distance1 = (x, y) -> Math.sqrt(Math.pow(y[1]-x[1],2) + Math.pow(y[0]-x[0], 2));
        CLARANS<Double[]> clarans = new CLARANS<>(data, distance1, 3);
        System.out.println(clarans);

此代码使用欧几里得算法创建CLARANS聚类(请参见//此处注释下面的行)。我应该用自己的距离矩阵来更改它,希望在Smile中有一种方法可以做到这一点。

1 个答案:

答案 0 :(得分:1)

您可能会使用

Distance<Integer> d = (i,j) -> matrix[i][j];

聚类对象编号,而不是向量。

但是值得一看的是ELKI,它具有用于距离矩阵的预定义类,并为对象集使用优化表示,而不必像上面的lambda中那样使用昂贵的盒装Integer。因为ij是装箱的整数,所以每次距离计算都需要附加的内存间接寻址(和缓存未命中),这会大大降低性能。它还具有更好的FastCLARANS算法,以及FastPAM,据说速度要快O(k)倍。