这是本文档旧的修订版!
下载:文本聚类
下载:
package cn.edu.bjut.textmining.chapter5; import java.util.ArrayList; import java.util.Collections; import java.util.List; import cn.edu.bjut.textmining.util.TextVectorizer; /** 自底向上平均连接;每步比较所有现存簇对。 */ public final class AverageLinkage { private AverageLinkage() {} public static double distance(List<Integer> a, List<Integer> b, double[][] vectors) { double total = 0; for (int i : a) { for (int j : b) { total += TextVectorizer.cosineDistance(vectors[i], vectors[j]); } } return total / ((double) a.size() * b.size()); } public static int[] fit(double[][] vectors, int k, boolean printSteps) { KMeansEngine.validate(vectors); if (k < 1 || k > vectors.length) { throw new IllegalArgumentException("目标簇数无效"); } List<List<Integer>> clusters = new ArrayList<>(); for (int i = 0; i < vectors.length; i++) { clusters.add(new ArrayList<>(Collections.singletonList(i))); } int step = 0; while (clusters.size() > k) { double minimum = Double.POSITIVE_INFINITY; int a = -1, b = -1; for (int i = 0; i < clusters.size(); i++) { for (int j = i + 1; j < clusters.size(); j++) { double d = distance(clusters.get(i), clusters.get(j), vectors); if (d < minimum) { minimum = d; a = i; b = j; } } } if (printSteps) { System.out.printf( "第%d步:%s + %s,平均距离=%.9f%n", ++step, names(clusters.get(a)), names(clusters.get(b)), minimum); } clusters.get(a).addAll(clusters.get(b)); clusters.remove(b); } int[] labels = new int[vectors.length]; for (int c = 0; c < clusters.size(); c++) { for (int i : clusters.get(c)) { labels[i] = c; } } return labels; } private static String names(List<Integer> values) { List<String> names = new ArrayList<>(); for (int value : values) { names.add("N" + (value + 1)); } return names.toString(); } }
package cn.edu.bjut.textmining.chapter5; import cn.edu.bjut.textmining.chapter5.support.AverageLinkage; import cn.edu.bjut.textmining.chapter5.support.SampleNews; /** 九篇新闻的平均连接层次聚类。 */ public class HierarchicalClusteringDemo { public static void main(String[] args) { try { double[][] vectors = SampleNews.vectors(); int[] labels = AverageLinkage.fit(vectors, 3, true); SampleNews.printClusters(labels); } catch (Exception e) { e.printStackTrace(); } } }
评论