【问题标题】:Running clustering algorithms in ELKI在 ELKI 中运行聚类算法
【发布时间】:2013-02-25 21:59:43
【问题描述】:

我需要以编程方式使用 ELKI 来运行 k-medoids 聚类算法。我有一个相似度矩阵,希望输入到算法中。

是否有任何代码 sn-p 可用于如何运行 ELKI 算法? 我基本上需要知道如何创建DatabaseRelation 对象,创建自定义距离函数,以及读取算法输出。

不幸的是,ELKI 教程 (http://elki.dbs.ifi.lmu.de/wiki/Tutorial) 侧重于 GUI 版本和实现新算法,而试图通过查看 Javadoc 来编写代码令人沮丧。

如果有人知道任何易于使用的 k-medoid 库,那么这可能也是这个问题的一个很好的答案。

【问题讨论】:

标签: java cluster-analysis k-means elki


【解决方案1】:

我们非常感谢文档贡献! (更新:我现在已经把这篇帖子变成了new ELKI tutorial entry。)

出于多种原因,ELKI 确实提倡不要将其嵌入到其他 Java 应用程序中。这就是我们推荐使用 MiniGUI(或它构建的命令行)的原因。最好添加自定义代码,例如作为自定义 ResultHandler 或仅使用 ResultWriter 并解析生成的文本文件。

如果您真的想要将它嵌入到您的代码中(在很多情况下它很有用,特别是当您需要多个关系并希望评估不同的索引结构时),这是获取DatabaseRelation 的基本设置:

// Setup parameters:
ListParameterization params = new ListParameterization();
params.addParameter(FileBasedDatabaseConnection.INPUT_ID, filename);
// Add other parameters for the database here!

// Instantiate the database:
Database db = ClassGenericsUtil.parameterizeOrAbort(
    StaticArrayDatabase.class,
    params);
// Don't forget this, it will load the actual data...
db.initialize();

Relation<DoubleVector> vectors = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
Relation<LabelList> labels = db.getRelation(TypeUtil.LABELLIST);

如果您想编程更通用,请使用NumberVector&lt;?&gt;

为什么我们(目前)不建议将 ELKI 用作“库”:

  1. API 仍在发生很大变化。我们不断添加选项,但我们无法(还)提供稳定的 API。命令行/MiniGUI/参数化更加稳定,因为默认值的处理——参数化只列出了非默认参数,所以只有当这些变化你会注意到。

    在上面的代码示例中,请注意我也使用了这种模式。解析器、数据库等的更改可能不会影响这个程序!

  2. 内存使用: 数据挖掘是相当消耗内存的。如果您使用 MiniGUI 或命令行,则在任务完成时您有一个很好的cleanup。如果您从 Java 调用它,更改会非常高,您会在某处保留一些引用,最终会泄漏 大量 内存。所以不要使用上述模式,除非你完成后确保对象被正确清理

    通过从命令行运行 ELKI,您可以免费获得两件事:

    1. 没有内存泄漏。任务完成后,进程退出并释放所有内存。

    2. 无需为相同的数据重新运行两次。后续分析不需要重新运行算法。

  3. ELKI 有充分的理由不被设计为可嵌入库。 ELKI 有大量的选项和功能,这是有代价的,无论是在运行时(尽管它可以轻松胜过 R 和 Weka,例如!)内存使用,尤其是在代码复杂性方面。 ELKI 是为研究数据挖掘算法而设计的,而不是让它们易于包含在任意应用程序中。相反,如果您遇到特定问题,您应该使用 ELKI 找出哪种方法效果好,然后针对您的问题以优化的方式重新实现该方法

使用 ELKI 的最佳方式

这里有一些提示和技巧:

  1. 使用 MiniGUI 构建命令行。请注意,在“GUI”的日志记录窗口中,它会显示相应的命令行参数 - 从命令行运行 ELKI 很容易编写脚本,并且可以很容易地分发到多台计算机,例如通过 Grid Engine。

    #!/bin/bash
    for k in $( seq 3 39 ); do
        java -jar elki.jar KDDCLIApplication \
            -dbc.in whatever \
            -algorithm clustering.kmeans.KMedoidsEM \
            -kmeans.k $k \
            -resulthandler ResultWriter -out.gzip \
            -out output/k-$k 
    done
    
  2. 使用索引。对于许多算法,索引结构可以产生巨大的影响! (但您需要研究哪些索引可用于哪些算法!)

  3. 考虑使用ResultWriter 等扩展点。连接到这个 API 对您来说可能是最简单的方法,然后使用 ResultUtil 选择您想要以您自己的首选格式输出或分析的结果:

    List<Clustering<? extends Model>> clusterresults =
        ResultUtil.getClusteringResults(result);
    
  4. 要识别对象,请使用标签和LabelList 关系。默认解析器会在看到带有数字属性的文本时执行此操作,即诸如

    之类的文件
    1.0 2.0 3.0 ObjectLabel1
    

    可以通过标签轻松识别对象!

更新:请参阅ELKI tutorial created out of this post 了解更新。

【讨论】:

  • 感谢您的详细解答。我现在需要一些现成但易于嵌入的东西,所以这次我会跳过,但我会牢记 ELKI。很高兴提出一个导致新教程的问题:)
【解决方案2】:

ELKI 的文档非常少(我不知道为什么他们在示例中没有包含一个简单的“hello world”程序)

您可以尝试 Java-ML。它的文档对用户更加友好,并且确实具有 K-medoid。

使用 Java-ML 的聚类示例 | http://java-ml.sourceforge.net/content/clustering-basics

K-medoid | http://java-ml.sourceforge.net/api/0.1.7/

【讨论】:

  • 随时贡献文档。提供文档通常是最好的,因为软件的作者通常倾向于“在他自己的盒子里”思考。
  • 我已经用 JavaML 尝试了一个玩具示例,但我得到了一个奇怪的 java.util.NoSuchElementException。我可能应该写一个关于它的问题。我现在对所有这些库有点沮丧,所以我想我会自己实现 K-Medoids...
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 2017-03-15
  • 2014-05-18
  • 2016-08-14
相关资源
最近更新 更多