我想用自定义距离矩阵而不是内置算法(即欧几里得)对数据进行聚类。而且似乎没有明确的方法。
我尝试将一些代码添加到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中有一种方法可以做到这一点。
答案 0 :(得分:1)
您可能会使用
Distance<Integer> d = (i,j) -> matrix[i][j];
聚类对象编号,而不是向量。
但是值得一看的是ELKI,它具有用于距离矩阵的预定义类,并为对象集使用优化表示,而不必像上面的lambda中那样使用昂贵的盒装Integer
。因为i
和j
是装箱的整数,所以每次距离计算都需要附加的内存间接寻址(和缓存未命中),这会大大降低性能。它还具有更好的FastCLARANS算法,以及FastPAM,据说速度要快O(k)倍。