我有一个一维数据集,其直方图显示了多个局部最大值,因此我知道我的一维空间中有多个区域,这些区域的数据更加密集。我想确定这些密集区域的边界,以使我能够对某个数据点所在的密集区域/群集进行分类。为此,我使用OPTICS,因为它应该能够更好地处理比较的群集之间的不同密度到DBSCAN。
我在Java代码中使用ELKI(0.6.0版)(我知道ELKI团队不建议将ELKI嵌入Java中,但是我需要对许多数据集重复我的工作流程,因此,在我的情况下,最好将其自动化) 。下面的代码段显示了群集开始和结束项目的索引。 ELKI documentation on OPTICSModel并没有明确定义这些索引号对应的内容,但是我假设这些是数据库的增强集群顺序中的开始和结束数据项的索引(例如OPTICS.run()-的ClusterOrderResult对象-创建的),而不是数据库本身的开始和结束数据项的索引(无序)。
ListParameterization opticsParams = new ListParameterization();
opticsParams.addParameter(OPTICSXi.XI_ID, 0.01);
opticsParams.addParameter(OPTICS.MINPTS_ID, 100);
OPTICSXi<DoubleDistance> optics = ClassGenericsUtil.parameterizeOrAbort(OPTICSXi.class, opticsParams);
ArrayAdapterDatabaseConnection arrayAdapterDatabaseConnection = new ArrayAdapterDatabaseConnection(myListOfOneDimensionalFeatureVectors.toArray(new double[myListOfOneDimensionalFeatureVectors.size()][2]));
ListParameterization dbParams = new ListParameterization();
dbParams.addParameter(AbstractDatabase.Parameterizer.INDEX_ID, RStarTreeFactory.class);
dbParams.addParameter(RStarTreeFactory.Parameterizer.BULK_SPLIT_ID, SortTileRecursiveBulkSplit.class);
dbParams.addParameter(AbstractDatabase.Parameterizer.DATABASE_CONNECTION_ID, arrayAdapterDatabaseConnection);
Database db = ClassGenericsUtil.parameterizeOrAbort(StaticArrayDatabase.class, dbParams);
db.initialize();
result = optics.run(db);
List<Cluster<OPTICSModel>> clusters = result.getAllClusters();
for(Cluster<OPTICSModel> cluster : clusters){
if(!cluster.isNoise())
System.out.println(cluster.getModel().getStartIndex() + ", "+ cluster.getModel().getEndIndex() +"; ");
}
现在,我想知道一维空间在哪里开始和结束。因此,我想检索与上面我的代码已经获得的开始和结束索引相对应的数据项。我假设我需要一个ClusterOrderResult对象,然后可以从该对象检索获得的索引。但是,在文档中,似乎不可能从我通过调用Opticals.run()获得的“聚类”结果对象中检索到这种东西。由于似乎无法获得此有序数据库,因此我天真地尝试从原始输入数据集中获取索引,而不是用下面的println替换上面代码中的println:
System.out.println(myListOfOneDimensionalFeatureVectors.get(cluster.getModel().getStartIndex())[0] + ", "+ myListOfOneDimensionalFeatureVectors.get(cluster.getModel().getEndIndex())[0] +"; ";
但是,正如我已经预料到的那样,索引似乎并不属于原始输入文件,因为这会在我的一维空间中以比结束边界更低的值定期打印结束边界。是否有人知道任何方法来获取与使用OPTICS聚类找到的开始和结束索引相对应的原始一维数据值?我想稍后在代码中使用这些值。
最佳答案
出于自动化的目的,从命令行调用ELKI效果很好。那是我的首选方式,因为这种方式将每次运行很好地隔离在自己的JVM中。
然后,您可以轻松地从输出文件访问此数据。
为什么使用旧版本的ELKI?由于删除了泛型,因此0.6.5版本要好得多。尽管我现在切换到了github版本。
如果要直接访问ClusterOrder
对象,则将其作为子结果附加到群集对象。您应该能够使用
ClusterOrder clusterOrder = ResultUtil.filterResults(clustering, ClusterOrder.class).get(0);
及其对象ID,通过:
ArrayDBIDs ids = DBIDUtil.ensureArray(clusterOrder.getDBIDs());
(
ensureArray
是开销,但无论如何它都是noop-它是强制转换或转换操作,这里将是强制转换;至少在我的ELKI版本中,id始终存储为ArrayDBID)数组迭代器(
DBIDArrayIter it = ids.iter()
)可以通过seek(offset)
移动到某个位置。因此,您应该可以使用类似DBIDArrayIter it = ids.iter();
NumberVector vec = relation.get(it.seek(model.getStartIndex()));
ELKI中的迭代器对于Java API来说很奇怪,但是如果您对所有访问使用单个迭代器,则会非常快。
您的ELKI问题部分非常重要。但是,从统计角度来看,对一维数据使用OPTICS没有意义。在一维数据上,改用适当的内核密度估计。当您的数据过于复杂而无法使用适当的统计工具进行建模时,OPTICS是一种粗略而粗略的方法。 OPTICS使用非常原始的内核密度,而xi方法是从密度图中非常幼稚地提取簇的方法……至少在一维数据上,统计数据提供了更强大的工具。 ELKI有一个叫做
KNNKernelDensityMinimaClustering
的实现,但是我还没有使用它。但是内核密度估计应该在任何统计工具包中都可用,因此我将尝试此类。