如何在ELKI中存储索引?

时间:2018-03-13 11:55:37

标签: indexing store dbscan elki

我正在使用ELKI 0.7.2(master)在大型数据集上运行带有R *树的DBSCAN。之后,我需要持久存储树,以便在评估新数据点是否为噪声时可以在内存中重新加载。为此,我尝试了PersistentPageFileFactory并得到以下错误

java.lang.ClassCastException: de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode cannot be cast to de.lmu.ifi.dbs.elki.persistent.ExternalizablePage

虽然我只是修改了RStarTreeNode来实现ExternalizablePage接口,但它并没有帮助。当我使用OnDiskArrayPageFileFactory时,我得到了另一个错误,如下所示

java.lang.RuntimeException: IOException occurred during reading of page 0
at de.lmu.ifi.dbs.elki.persistent.OnDiskArrayPageFile.readPage(OnDiskArrayPageFile.java:113)

有没有办法存储索引,例如R *树,放入文件并从文件中加载?

非常感谢提前!

2 个答案:

答案 0 :(得分:0)

磁盘反序列化代码多年未使用,因此很可能已损坏。

我甚至不确定它是否完全支持从磁盘独立读回索引;我假设它仅用于模拟磁盘索引以进行基准测试(即,它将从磁盘读取和写入数据,但它可能无法读取现有索引)。

这不是我需要的功能,所以除了重构之外我从未研究过这个代码。我实际上一直试图慢慢删除大部分代码(特别是ExternalizablePage),因为我没有给人的印象。

我有一个R-tree的重写版本,更适合实际的磁盘使用。但它还没有完成,它还不支持R * -tree重新插入。因此代码尚未发布(不幸的是,可能永远不会完成)。

因此,您可能需要重写该代码的大部分内容以使其可用。

如果您这样做,请在Github上分享您的修改。

答案 1 :(得分:0)

我想问同样的问题。我的情况是一样的。如果数据集为10k或100K,则无需存储群集, 但是如果要获取1M或更多数据集的集群,则需要花费超过1个小时的时间。我发现很少有解决方法如何在磁盘上存储模型。 要检测离群值,您必须从没有噪音的数据集中获取KnnQuery。它花费的时间少于群集计数(1M数据集需要1-3分钟)。 因此,您可以计算聚类并仅存储属于聚类的元素并使用它。

首先,按照此处所述计算聚类。 https://elki-project.github.io/howto/java_api 处理结果(仅保留不是噪声的点):

    List<String> clusterPoints = new ArrayList<>(); // List which will be stored in file

    for (Cluster<Model> cluster : clusters.getAllClusters()) {
        if (!cluster.isNoise()) { // write to output only not noises

            for (DBIDIter iterator = cluster.getIDs().iter(); iterator.valid(); iterator.advance()) {
                NumberVector vector = relation.get(iterator);

                for (int i = 0; i < vector.toArray().length; i++) {
                    clusterPoints.add(String.valueOf(vector.toArray()[i]));
                }
            }
        }
    }

将此clusterPoints保存在文件中。要还原群集,请按照https://elki-project.github.io/howto/java_api#creating-a-database

的说明从文件中的点获取关联
    double[] pointToDetect = YOUR_POINT_TO_DETECT_OUTLIER;
    // get db as described here: https://elki-project.github.io/howto/java_api#creating-a-database
    Relation<NumberVector> relation = db.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
    NumberVector vector = DoubleVector.FACTORY.newNumberVector(pointToDetect);

    KNNQuery<NumberVector> knnQuery = QueryUtil.getKNNQuery(relation, EuclideanDistanceFunction.STATIC); // or any other DistanceFunction
    KNNList list = model.getKnnQuery().getKNNForObject(vector, NEAREST_NEIGHBORS_NUMBER);

    DoubleDBIDPair pairNearest = list.get(0);
    double distanceNearest = pairNearest.doubleValue();
    if (distanceNearest > EPSILON) {
        log.warn("Outlier detected!");
    }

它工作正常,但是我发现在某些数据群集上,恢复需要花费很长时间。         这就是为什么仍需要集群存储实现的原因。