【JAVA实现】层次聚类算法
来源:互联网 发布:vscode nodejs 调试 编辑:程序博客网 时间:2024/05/17 23:57
聚类算法属于机器学习中一种无监督学习算法。聚类方法一般可以分为层次聚类与非层次聚类两种。其中层次聚类算法又可以分为合并法与分解法;同样非层次聚类算法也可以分为多种,常用的有K-means算法。这篇博客先来实现层次聚类算法中的合并法,我会在下一篇博文中讲述K-means算法。
其中,合并法是指:初始阶段,将每个样本点当做其类簇,然后合并这些原子类簇直至达到预期的类簇数或者其他终止条件。
算法实现:
输入: K:目标类簇数D:样本点集合
输出:K个类簇集合
方法:
1)将D中各个样本点当做类簇集合
2)repeat
3) 找到分属两个不同类簇,且距离最近的样本点对
4) 将两个类簇合并
5) util 类簇数=K
下面,我将用如下数据集作做测试:
package hierarchicalClustering;import java.util.List;/** * @author shenchao * * 封装每一个聚类 * */public class Cluster {/** * 左节点 */private Cluster left;/** * 右节点 */private Cluster right;/** * data */private List<Double> vector;/** * id */private int id;/** * 距离 */private double distance;/** * 标签名 */private String name;public Cluster(){}public Cluster(Cluster left, Cluster right, List<Double> vector, int id,double distance) {this.left = left;this.right = right;this.vector = vector;this.id = id;this.distance = distance;}public Cluster getLeft() {return left;}public void setLeft(Cluster left) {this.left = left;}public Cluster getRight() {return right;}public void setRight(Cluster right) {this.right = right;}public List<Double> getVector() {return vector;}public void setVector(List<Double> vector) {this.vector = vector;}public int getId() {return id;}public void setId(int id) {this.id = id;}public double getDistance() {return distance;}public void setDistance(double distance) {this.distance = distance;}public String getName() {return name;}public void setName(String name) {this.name = name;}}将每个聚类用如上形式封装。
package hierarchicalClustering;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class HierarchicalClustering {private List<Cluster> clusters = null;public HierarchicalClustering() throws IOException {initData();}/** * 初始化数据集 * * @throws IOException */private void initData() throws IOException {clusters = new ArrayList<Cluster>();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(HierarchicalClustering.class.getClassLoader().getResourceAsStream("data.txt")));String line = null;int i = 0;while ((line = bufferedReader.readLine()) != null) {String[] s = line.split("\t");Cluster cluster = new Cluster();List<Double> list = new ArrayList<Double>();for (String string : s) {try{list.add(Double.parseDouble(string));}catch(Exception e) {cluster.setName(string);}}cluster.setId(i++);cluster.setVector(list);clusters.add(cluster);}}public Cluster hcluster() {// 用distances来缓存任意两聚类之间的距离,其中map集合的键为两个聚类的idMap<Integer[], Double> distances = new HashMap<Integer[], Double>();int currentId = -1;while (clusters.size() > 1) {// 最短距离的两聚类idint lowestpair1 = 0;int lowestpair2 = 1;// 最短距离double closest = EuclideanMetric.sim_distance(clusters.get(0).getVector(), clusters.get(1).getVector());for (int i = 0; i < clusters.size(); i++) {for (int j = i + 1; j < clusters.size(); j++) {Integer[] key = { clusters.get(i).getId(),clusters.get(j).getId() };if (!distances.containsKey(key)) {distances.put(key, EuclideanMetric.sim_distance(clusters.get(i).getVector(), clusters.get(j).getVector()));}double d = distances.get(key);if (d < closest) {closest = d;lowestpair1 = i;lowestpair2 = j;}}}// 计算两个最短距离聚类的平均值List<Double> midvec = mergevec(clusters.get(lowestpair1),clusters.get(lowestpair2));Cluster cluster = new Cluster(clusters.get(lowestpair1),clusters.get(lowestpair2),midvec,currentId,closest);currentId -= 1;//注意删除顺序,先删除大的id号,否则会出现越界if (lowestpair1 < lowestpair2) {clusters.remove(clusters.get(lowestpair2));clusters.remove(clusters.get(lowestpair1));}else {clusters.remove(clusters.get(lowestpair1));clusters.remove(clusters.get(lowestpair2));}clusters.add(cluster);}return clusters.get(0);}private List<Double> mergevec(Cluster cluster1, Cluster cluster2) {List<Double> midvec = new ArrayList<Double>();for (int i = 0; i < cluster1.getVector().size(); i++) {midvec.add((cluster1.getVector().get(i) + cluster2.getVector().get(i)) / 2.0);}return midvec;}/** * 打印输出 */public void printCluster(Cluster cluster,int n) {for (int i = 0; i < n; i++) {System.out.print(" ");}//负数标记代表这是一个分支if (cluster.getId() < 0) {System.out.println("-");}else {//代表是一个叶子节点System.out.println(cluster.getName());}if (cluster.getLeft()!= null) {printCluster(cluster.getLeft(),++n);}if (cluster.getRight()!=null) {printCluster(cluster.getRight(), ++n);}}public static void main(String[] args) throws IOException {HierarchicalClustering hierarchicalClustering = new HierarchicalClustering();hierarchicalClustering.printCluster(hierarchicalClustering.hcluster(), 0);}}两个样本点的距离我使用了欧几里得算法(http://blog.csdn.net/c_son/article/details/43889195)得出,当然根据实际情况你也可以采用皮尔逊相关度算法等,http://blog.csdn.net/c_son/article/details/43876479
最后,我已树状图的形式在控制台输出:
仔细观察,可以发现,里面包含三棵子树,和上面的图表显示一致。
此算法缺点:效率比较低下,每次循环都要计算每两个类簇之间的距离,有些可能要重复计算。还有一不足是,不具有再分配能力,即如果样本点A在某次迭代过程中已经划分给类簇C1,那么在后面的迭代过程中永远属于C1,这将影响聚类结果。
改进:一般情况下,层次聚类通常和划分式聚类算法组合,这样既可以解决效率问题,又可以解决样本点再分配问题,这样的算法有BIRCH算法等。首先把邻近点划分到微簇,然后对这些微簇进行k-means算法。
OK,如有问题,欢迎大家和我一起学习交流。
- 【JAVA实现】层次聚类算法
- 层次聚类算法java实现
- 聚类算法之层次聚类(Java实现)
- 层次聚类算法的python实现
- 层次聚类算法及其实现
- 层次聚类算法原理及实现
- 层次聚类 java和matlab实现
- 层次聚类实例以及Java实现
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法
- 层次聚类算法的原理及实现Hierarchical Clustering
- 为什么Java程序占用的内存比实际分配给它的要多
- Android中ImageView内存溢出
- POJ 3669 Meteor Shower (bfs)
- 小范围解决 重复提交表单的问题
- 如何给你的Android 安装文件(APK)瘦身
- 【JAVA实现】层次聚类算法
- Sublime Text2 2.0.2版本破解以及汉化方法
- 内核函数mmap的实现原理,机制
- Android中向drawable图片资源命名须知
- JVM性能调优
- 今天给大家分享ios中的夜间模式(通知中心)
- 【Android实战】实现新浪微博第三方登录获取用户信息
- USACO Ski Course Design
- Codeforces Round #291 (Div. 2)D.R2D2 and Droid Army——RMQ+二分