聚类分析之层次聚类算法

层次聚类算法:

前面介绍的K-means算法和K中心点算法都属于划分式(partitional)聚类算法。层次聚类算法是将所有的样本点自底向上合并组成一棵树或者自顶向下分裂成一棵树的过程,这两种方式分别称为凝聚和分裂。

凝聚层次算法:

初始阶段,将每个样本点分别当做其类簇,然后合并这些原子类簇直至达到预期的类簇数或者其他终止条件。

分裂层次算法:

初始阶段,将所有的样本点当做同一类簇,然后分裂这个大类簇直至达到预期的类簇数或者其他终止条件。

两种算法的代表:

传统的凝聚层次聚类算法有AGENES,初始时,AGENES将每个样本点自为一簇,然后这些簇根据某种准则逐渐合并,例如,如果簇C1中的一个样本点和簇C2中的一个样本点之间的距离是所有不同类簇的样本点间欧几里得距离最近的,则认为簇C1和簇C2是相似可合并的。

传统的分裂层次聚类算法有DIANA,初始时DIANA将所有样本点归为同一类簇,然后根据某种准则进行逐渐分裂,例如类簇C中两个样本点A和B之间的距离是类簇C中所有样本点间距离最远的一对,那么样本点A和B将分裂成两个簇C1和C2,并且先前类簇C中其他样本点根据与A和B之间的距离,分别纳入到簇C1和C2中,例如,类簇C中样本点O与样本点A的欧几里得距离为2,与样本点B的欧几里得距离为4,因为Distance(A,O)<Distance(B,O)那么O将纳入到类簇C1中。

如图所示:

算法:AGENES。传统凝聚层次聚类算法

输入:K:目标类簇数 D:样本点集合

输出:K个类簇集合

方法:1) 将D中每个样本点当做其类簇;

2) repeat

3)    找到分属两个不同类簇,且距离最近的样本点对;

4)    将两个类簇合并;

5) util 类簇数=K

算法:DIANA。传统分裂层次聚类算法

输入:K:目标类簇数 D:样本点集合

输出:K个类簇集合

方法:1) 将D中所有样本点归并成类簇;

2) repeat

3)    在同类簇中找到距离最远的样本点对;

4)    以该样本点对为代表,将原类簇中的样本点重新分属到新类簇

5) util 类簇数=K

缺点:

传统的层次聚类算法的效率比较低O(tn2) t:迭代次数 n:样本点数,最明显的一个缺点是不具有再分配能力,即如果样本点A在某次迭代过程中已经划分给类簇C1,那么在后面的迭代过程中A将永远属于类簇C1,这将影响聚类结果的准确性。

改进:

一般情况下,层次聚类通常和划分式聚类算法组合,这样既可以解决算法效率的问题,又能解决样本点再分配的问题,在后面将介绍BIRCH算法。首先把邻近样本点划分到微簇(microcluseters)中,然后对这些微簇使用K-means算法。

----------------贴上本人实现的AGENES算法,大家有兴趣可以把DIANA算法自己实现下---------------

package com.agenes;

public class DataPoint {

String dataPointName; // 样本点名

Cluster cluster; // 样本点所属类簇

private double dimensioin[]; // 样本点的维度

public DataPoint(){

}

public DataPoint(double[] dimensioin,String dataPointName){

this.dataPointName=dataPointName;

this.dimensioin=dimensioin;

}

public double[] getDimensioin() {

return dimensioin;

}

public void setDimensioin(double[] dimensioin) {

this.dimensioin = dimensioin;

}

public Cluster getCluster() {

return cluster;

}

public void setCluster(Cluster cluster) {

this.cluster = cluster;

}

public String getDataPointName() {

return dataPointName;

}

public void setDataPointName(String dataPointName) {

this.dataPointName = dataPointName;

}

}

package com.agenes;

import java.util.ArrayList;

import java.util.List;

public class Cluster {

private List<DataPoint> dataPoints = new ArrayList<DataPoint>(); // 类簇中的样本点

private String clusterName;

public List<DataPoint> getDataPoints() {

return dataPoints;

}

public void setDataPoints(List<DataPoint> dataPoints) {

this.dataPoints = dataPoints;

}

public String getClusterName() {

return clusterName;

}

public void setClusterName(String clusterName) {

this.clusterName = clusterName;

}

}

package com.agenes;

import java.util.ArrayList;

import java.util.List;

public class ClusterAnalysis {

public List<Cluster> startAnalysis(List<DataPoint> dataPoints,int ClusterNum){

List<Cluster> finalClusters=new ArrayList<Cluster>();

List<Cluster> originalClusters=initialCluster(dataPoints);

finalClusters=originalClusters;

while(finalClusters.size()>ClusterNum){

double min=Double.MAX_VALUE;

int mergeIndexA=0;

int mergeIndexB=0;

for(int i=0;i<finalClusters.size();i++){

for(int j=0;j<finalClusters.size();j++){

if(i!=j){

Cluster clusterA=finalClusters.get(i);

Cluster clusterB=finalClusters.get(j);

List<DataPoint> dataPointsA=clusterA.getDataPoints();

List<DataPoint> dataPointsB=clusterB.getDataPoints();

for(int m=0;m<dataPointsA.size();m++){

for(int n=0;n<dataPointsB.size();n++){

double tempDis=getDistance(dataPointsA.get(m),dataPointsB.get(n));

if(tempDis<min){

min=tempDis;

mergeIndexA=i;

mergeIndexB=j;

}

}

}

}

} //end for j

}// end for i

//合并cluster[mergeIndexA]和cluster[mergeIndexB]

finalClusters=mergeCluster(finalClusters,mergeIndexA,mergeIndexB);

}//end while

return finalClusters;

}

private List<Cluster> mergeCluster(List<Cluster> clusters,int mergeIndexA,int mergeIndexB){

if (mergeIndexA != mergeIndexB) {

// 将cluster[mergeIndexB]中的DataPoint加入到 cluster[mergeIndexA]

Cluster clusterA = clusters.get(mergeIndexA);

Cluster clusterB = clusters.get(mergeIndexB);

List<DataPoint> dpA = clusterA.getDataPoints();

List<DataPoint> dpB = clusterB.getDataPoints();

for (DataPoint dp : dpB) {

DataPoint tempDp = new DataPoint();

tempDp.setDataPointName(dp.getDataPointName());

tempDp.setDimensioin(dp.getDimensioin());

tempDp.setCluster(clusterA);

dpA.add(tempDp);

}

clusterA.setDataPoints(dpA);

// List<Cluster> clusters中移除cluster[mergeIndexB]

clusters.remove(mergeIndexB);

}

return clusters;

}

// 初始化类簇

private List<Cluster> initialCluster(List<DataPoint> dataPoints){

List<Cluster> originalClusters=new ArrayList<Cluster>();

for(int i=0;i<dataPoints.size();i++){

DataPoint tempDataPoint=dataPoints.get(i);

List<DataPoint> tempDataPoints=new ArrayList<DataPoint>();

tempDataPoints.add(tempDataPoint);

Cluster tempCluster=new Cluster();

tempCluster.setClusterName("Cluster "+String.valueOf(i));

tempCluster.setDataPoints(tempDataPoints);

tempDataPoint.setCluster(tempCluster);

originalClusters.add(tempCluster);

}

return originalClusters;

}

//计算两个样本点之间的欧几里得距离

private double getDistance(DataPoint dpA,DataPoint dpB){

double distance=0;

double[] dimA = dpA.getDimensioin();

double[] dimB = dpB.getDimensioin();

if (dimA.length == dimB.length) {

for (int i = 0; i < dimA.length; i++) {

double temp=Math.pow((dimA[i]-dimB[i]),2);

distance=distance+temp;

}

distance=Math.pow(distance, 0.5);

}

return distance;

}

public static void main(String[] args){

ArrayList<DataPoint> dpoints = new ArrayList<DataPoint>();

double[] a={2,3};

double[] b={2,4};

double[] c={1,4};

double[] d={1,3};

double[] e={2,2};

double[] f={3,2};

double[] g={8,7};

double[] h={8,6};

double[] i={7,7};

double[] j={7,6};

double[] k={8,5};

//       double[] l={100,2};//孤立点

double[] m={8,20};

double[] n={8,19};

double[] o={7,18};

double[] p={7,17};

double[] q={8,20};

dpoints.add(new DataPoint(a,"a"));

dpoints.add(new DataPoint(b,"b"));

dpoints.add(new DataPoint(c,"c"));

dpoints.add(new DataPoint(d,"d"));

dpoints.add(new DataPoint(e,"e"));

dpoints.add(new DataPoint(f,"f"));

dpoints.add(new DataPoint(g,"g"));

dpoints.add(new DataPoint(h,"h"));

dpoints.add(new DataPoint(i,"i"));

dpoints.add(new DataPoint(j,"j"));

dpoints.add(new DataPoint(k,"k"));

//       dataPoints.add(new DataPoint(l,"l"));

dpoints.add(new DataPoint(m,"m"));

dpoints.add(new DataPoint(n,"n"));

dpoints.add(new DataPoint(o,"o"));

dpoints.add(new DataPoint(p,"p"));

dpoints.add(new DataPoint(q,"q"));

int clusterNum=3; //类簇数

ClusterAnalysis ca=new ClusterAnalysis();

List<Cluster> clusters=ca.startAnalysis(dpoints, clusterNum);

for(Cluster cl:clusters){

System.out.println("------"+cl.getClusterName()+"------");

List<DataPoint> tempDps=cl.getDataPoints();

for(DataPoint tempdp:tempDps){

System.out.println(tempdp.getDataPointName());

}

}

}

}

时间: 2024-10-10 15:33:06

聚类分析之层次聚类算法的相关文章

Python爬虫技术(从网页获取图片)+HierarchicalClustering层次聚类算法,实现自动从网页获取图片然后根据图片色调自动分类—Jason niu

网上教程太啰嗦,本人最讨厌一大堆没用的废话,直接上,就是干! 网络爬虫?非监督学习? 只有两步,只有两个步骤? Are you kidding me? Are you ok? 来吧,follow me, come on! 第一步:首先,我们从网上获取图片自动下载到自己电脑的文件内,如从网址,下载到F:\File_Python\Crawler文件夹内,具体代码请查看http://www.cnblogs.com/yunyaniu/p/8244490.html 第二步:我们利用非监督学习的Hierar

HierarchicalClustering:编写HierarchicalClustering层次聚类算法—Jason niu

from numpy import * class cluster_node: def __init__(self,vec,left=None,right=None,distance=0.0,id=None,count=1): self.left=left self.right=right self.vec=vec self.id=id self.distance=distance self.count=count def L2dist(v1,v2): return sqrt(sum((v1-v

看完这篇文章,包你懂得如何用Python实现聚类算法的层次算法!

什么是聚类 将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异.聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法. 聚类分析起源于分类学,但是聚类不等于分类.聚类与分类的不同在于,聚类所要求划分的类是未知的.聚类分析内容非常丰富,有系统聚类法.有序样品聚类法.动态聚类法.模糊聚类法.图论聚类法.聚类预报法等. 起步 层次聚类( Hierarchical Cluste

聚类分析之基于密度的聚类算法(DBSCAN)

一  什么是基于密度的聚类算法 由于层次聚类算法和划分式聚类算往往只能发现凸形的聚类簇.为了弥补这一缺陷,发现各种任意形状的聚类簇,开发出基于密度的聚类算法.这类算法认为,在整个样本空间点中,各目标类簇是由一群的稠密样本点组成的,而这些稠密样本点被低密度区域(噪声)分割,而算法的目的就是要过滤低密度区域,发现稠密样本点. 二  DBSCAN(Density-based Spatial Clustering of Applications with Noise) 是一种基于高密度联通区域的聚类算法

聚类算法之层次法

首先介绍聚类中的层次聚类算法.层次法又分为凝聚的层次聚类和分裂的层次聚类. 凝聚的方法:也称自底向上的方法,首先将每个对象作为单独的一个聚类,然后根据性质和规则相继地合并相近的类,直到所有的对象都合并为一个聚类中,或者满足一定的终止条件.经典的层次凝聚算法以AGNES算法为代表,改进的层次凝聚算法主要以BIRCH,CURE,ROCK,CHAMELEON为代表.(后面详细介绍) 分裂的方法:也称自顶向下的方法,正好与凝聚法相反,首先将所有的对象都看作是一个聚类,然后在每一步中,上层类被分裂为下层更

聚类算法--K-means和k-mediods/密度聚类/层次聚类

目录 简述 K-means聚类 密度聚类 层次聚类 一.简述 聚类算法是常见的无监督学习(无监督学习是在样本的标签未知的情况下,根据样本的内在规律对样本进行分类). 在监督学习中我们常根据模型的误差来衡量模型的好坏,通过优化损失函数来改善模型.而在聚类算法中是怎么来度量模型的好坏呢?聚类算法模型的性能度量大致有两类: 1)将模型结果与某个参考模型(或者称为外部指标)进行对比,个人觉得认为这种方法用的比较少 2)另一种是直接使用模型的内部属性,比如样本之间的距离(闵可夫斯基距离)来作为评判指标,这

机器学习(6)之聚类算法(k-means\Canopy\层次聚类\谱聚类)

目录 1 聚类的定义 1.1 距离公式(相似度) 1.2 聚类的思想 2 K-means算法 2.1 K-means算法的思考 2.2 总结 3 二分K-Means算法 4 K-Means++算法 4.1 K-Means||算法 5 Canopy算法 5.1 应用场景 6 Mini Batch K-Means算法 7 层次聚类方法 7.1 AGNES算法中簇间距离 7.2 层次聚类优化算法 8 密度聚类 8.1 DBSCAN算法 8.1.1 基本概念 8.1.2 算法流程 8.1.3 DBSCA

【ML-7】聚类算法--K-means和k-mediods/密度聚类/层次聚类

目录 简述 K-means聚类 密度聚类 层次聚类 一.简述 聚类算法是常见的无监督学习(无监督学习是在样本的标签未知的情况下,根据样本的内在规律对样本进行分类). 在监督学习中我们常根据模型的误差来衡量模型的好坏,通过优化损失函数来改善模型.而在聚类算法中是怎么来度量模型的好坏呢?聚类算法模型的性能度量大致有两类: 1)将模型结果与某个参考模型(或者称为外部指标)进行对比,个人觉得认为这种方法用的比较少 2)另一种是直接使用模型的内部属性,比如样本之间的距离(闵可夫斯基距离)来作为评判指标,这

【转载】聚类算法小结

聚类算法总结:---------------------------------------------------------聚类算法的种类: 基于划分聚类算法(partition clustering) k-means: 是一种典型的划分聚类算法,它用一个聚类的中心来代表一个簇,即在迭代过程中选择的聚点不一定是聚类中的一个点,该算法只能处理数值型数据 k-modes: K-Means算法的扩展,采用简单匹配方法来度量分类型数据的相似度 k-prototypes: 结合了K-Means和K-M