我在java中编写了一个凝聚聚类算法,并且在删除操作时遇到了问题。当集群数量达到初始数量的一半时,它似乎总是失败。
在下面的示例代码中,clusters
是Collection<Collection<Integer>>
。
while(clusters.size() > K){
// determine smallest distance between clusters
Collection<Integer> minclust1 = null;
Collection<Integer> minclust2 = null;
double mindist = Double.POSITIVE_INFINITY;
for(Collection<Integer> cluster1 : clusters){
for(Collection<Integer> cluster2 : clusters){
if( cluster1 != cluster2 && getDistance(cluster1, cluster2) < mindist){
minclust1 = cluster1;
minclust2 = cluster2;
mindist = getDistance(cluster1, cluster2);
}
}
}
// merge the two clusters
minclust1.addAll(minclust2);
clusters.remove(minclust2);
}
经过几次循环后,clusters.remove(minclust2)
最终返回false,但我不明白为什么。
我通过首先创建10个集群来测试此代码,每个集群包含1到10之间的一个整数。距离是0到1之间的随机数。这是添加几个println语句后的输出。在簇数之后,我打印出实际的簇,合并操作和clusters的结果.remove(minclust2)。
Clustering: 10 clusters
[[3], [1], [10], [5], [9], [7], [2], [4], [6], [8]]
[5] <- [6]
true
Clustering: 9 clusters
[[3], [1], [10], [5, 6], [9], [7], [2], [4], [8]]
[7] <- [8]
true
Clustering: 8 clusters
[[3], [1], [10], [5, 6], [9], [7, 8], [2], [4]]
[10] <- [9]
true
Clustering: 7 clusters
[[3], [1], [10, 9], [5, 6], [7, 8], [2], [4]]
[5, 6] <- [4]
true
Clustering: 6 clusters
[[3], [1], [10, 9], [5, 6, 4], [7, 8], [2]]
[3] <- [2]
true
Clustering: 5 clusters
[[3, 2], [1], [10, 9], [5, 6, 4], [7, 8]]
[10, 9] <- [5, 6, 4]
false
Clustering: 5 clusters
[[3, 2], [1], [10, 9, 5, 6, 4], [5, 6, 4], [7, 8]]
[10, 9, 5, 6, 4] <- [5, 6, 4]
false
Clustering: 5 clusters
[[3, 2], [1], [10, 9, 5, 6, 4, 5, 6, 4], [5, 6, 4], [7, 8]]
[10, 9, 5, 6, 4, 5, 6, 4] <- [5, 6, 4]
false
[10,9,5,6,4,5,6,4 ......]从那里开始无限增长。
编辑:澄清一下,我正在为群集中的每个群集使用HashSet<Integer>
(HashSet<HashSet<Integer>>)
。
答案 0 :(得分:5)
阿。当您更改已在Set
(或Map
键)中的值时,它不一定在正确的位置,并且将缓存哈希码。你需要删除它,改变它,然后重新插入它。
答案 1 :(得分:1)
在显示的测试中,remove
在您第一次尝试删除包含多个Integer的Collection时失败。总是这样吗?
使用Collection的具体类型是什么?
答案 2 :(得分:0)
明显的问题是clusters.remove
可能正在使用equals
来查找要删除的元素。遗憾的是,集合上的equals
通常会比较元素是否相同,而不是相同的集合(我相信C#在这方面做出了更好的选择)。
一个简单的解决方法是将clusters
创建为Collections.newSetFromMap(new IdentityHashMap<Collection<Integer>, Boolean>())
(我认为)。