0

使用测试用例,我可以看到如何直接从 Java 中使用 ELKI,但现在我想从 MongoDB 读取我的数据,然后使用 ELKI 对地理(经纬度)数据进行聚类。

我只能使用 ELKI 对 CSV 文件中的数据进行聚类。是否可以将 de.lmu.ifi.dbs.elki.database.Database 与 MongoDB 连接?我可以从java调试器中看到de.lmu.ifi.dbs.elki.database.Database中有一个databaseconnection字段。

我查询 MongoDB 为每一行创建 POJO,现在我想使用 ELKI 对这些对象进行聚类。

可以从 MongoDB 读取数据并将其写入 CSV 文件,然后使用 ELKI 读取该 CSV 文件,但我想知道是否有更简单的解决方案。

---------发现_1:

ELKI - 使用 List<String> 对象填充数据库我发现我需要实现 de.lmu.ifi.dbs.elki.datasource.DatabaseConnection 并专门覆盖返回 MultiObjectsBundle 实例的 loadData() 方法。

所以我认为我应该用 MultiObjectsBundle 包装一个 POJO 列表。现在我正在查看 MultiObjectsBundle,看起来数据应该保存在列中。为什么列数据类型是 List> 不应该是 List?只是您要聚类的项目列表?

我有点困惑。ELKI 怎么知道它应该查看 POJO 的 long 和 lat?我在哪里告诉 ELKI 这样做?使用 de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation?

---------发现_2:

我尝试使用 ArrayAdapterDatabaseConnection 并尝试实现 DatabaseConnection。对不起,我需要用非常简单的术语来理解。

这是我的聚类代码:

    int minPts=3;
    double eps=0.08; 
    double[][] data1 = {{-0.197574246, 51.49960695}, {-0.084605692, 51.52128377}, {-0.120973687, 51.53005939}, {-0.156876, 51.49313}, 
            {-0.144228881, 51.51811784}, {-0.1680743, 51.53430039}, {-0.170134484,51.52834133}, { -0.096440751, 51.5073853}, 
            {-0.092754157, 51.50597426}, {-0.122502346, 51.52395143}, {-0.136039674, 51.51991453}, {-0.123616824, 51.52994371}, 
            {-0.127854211, 51.51772703}, {-0.125979294, 51.52635795}, {-0.109006325, 51.5216612}, {-0.12221963, 51.51477076}, {-0.131161087, 51.52505093} };


    //      ArrayAdapterDatabaseConnection dbcon = new ArrayAdapterDatabaseConnection(data1);
    DatabaseConnection dbcon = new MyDBConnection();

    ListParameterization params = new ListParameterization();
    params.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.MINPTS_ID, minPts);
    params.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.EPSILON_ID, eps);
    params.addParameter(DBSCAN.DISTANCE_FUNCTION_ID, EuclideanDistanceFunction.class);
    params.addParameter(AbstractDatabase.Parameterizer.DATABASE_CONNECTION_ID, dbcon);
    params.addParameter(AbstractDatabase.Parameterizer.INDEX_ID,
            RStarTreeFactory.class);
    params.addParameter(RStarTreeFactory.Parameterizer.BULK_SPLIT_ID, 
            SortTileRecursiveBulkSplit.class);
    params.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 1000);

    Database db = ClassGenericsUtil.parameterizeOrAbort(StaticArrayDatabase.class, params);
    db.initialize();

    GeneralizedDBSCAN dbscan = ClassGenericsUtil.parameterizeOrAbort(GeneralizedDBSCAN.class, params);

    Relation<DoubleVector> rel = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
    Relation<ExternalID> relID = db.getRelation(TypeUtil.EXTERNALID);

    DBIDRange ids = (DBIDRange) rel.getDBIDs();
    Clustering<Model> result = dbscan.run(db);  

    int i =0;
    for(Cluster<Model> clu : result.getAllClusters()) {
        System.out.println("#" + i + ": " + clu.getNameAutomatic());
        System.out.println("Size: " + clu.size());

        System.out.print("Objects: ");
        for(DBIDIter it = clu.getIDs().iter(); it.valid(); it.advance()) {
           DoubleVector v = rel.get(it);
           ExternalID exID = relID.get(it);
           System.out.print("DoubleVec: ["+v+"]");
           System.out.print("ExID: ["+exID+"]");

           final int offset = ids.getOffset(it);
           System.out.print(" " + offset);
        }
        System.out.println();
        ++i;
    } 

ArrayAdapterDatabaseConnection 产生两个集群,当我设置 epsilon=0.008 dbscan 开始创建集群时,我只需要使用 epsilon 的值。当我设置 epsilon=0.04 时,所有项目都在 1 个集群中。

我也尝试过实现 DatabaseConnection:

@Override
public MultipleObjectsBundle loadData() { 
    MultipleObjectsBundle bundle = new MultipleObjectsBundle(); 

    List<Station> stations = getStations();
    List<DoubleVector> vecs = new ArrayList<DoubleVector>();
    List<ExternalID> ids = new ArrayList<ExternalID>();

    for (Station s : stations){

        String strID = Integer.toString(s.getId());
        ExternalID i = new ExternalID(strID);
        ids.add(i);     

        double[] st = {s.getLongitude(), s.getLatitude()};
        DoubleVector dv = new DoubleVector(st); 
        vecs.add(dv);
    } 

    SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, 2, 2, DoubleVector.FACTORY.getDefaultSerializer());

    bundle.appendColumn(type, vecs);      
    bundle.appendColumn(TypeUtil.EXTERNALID, ids);
    return bundle;
} 

这些 long/lat 与 ID 相关联,我需要将它们链接回此 ID 到值。使用 ID 偏移量(在上面的代码中)是唯一的方法吗?我尝试添加 ExternalID 列,但我不知道如何检索特定 NumberVector 的 ExternalID?

同样在看到使用 ELKI 的距离函数后,我尝试使用 Elki 的 longLatDistance,但它不起作用,我找不到任何示例来实现它。

4

1 回答 1

0

数据源的接口称为DatabaseConnection.

数据库连接的JavaDoc

您可以实现基于 MongoDB 的接口来获取数据。

它不是复杂的接口,它有一个单一的方法。

于 2015-10-29T12:37:54.683 回答