dist({m1,m2},{m3,m4})=min(dist(m1,m3),dist(m1,m4),dist(m2,m3),dist(m2,m4))
dist({m1,m2},{m3,m4})=(dist(m1,m3)+dist(m1,m4)+dist(m2,m3)+dist(m2,m4))/4
AGNES(Agglomerative Nesting) 是凝聚的层次聚类算法,如果簇C1中的一个对象和簇C2中的一个对象之间的距离是所有属于不同簇的对象间欧式距离中最小的,C1和C2可能被合并。这是一种单连接方法,其每个簇可以被簇中的所有对象代表,两个簇之间的相似度由这两个簇中距离最近的数据点对的相似度来确定。
算法描述:
输入:包含n个对象的数据库,终止条件簇的数目k
输出:k个簇
(1) 将每个对象当成一个初始簇
(2) Repeat
(3) 根据两个簇中最近的数据点找到最近的两个簇
(4) 合并两个簇,生成新的簇的集合
(5) Until达到定义的簇的数目
算法性能:
(1) 简单,但遇到合并点选择困难的情况。
(2) 一旦一组对象被合并,不能撤销
(3) 算法的复杂度为O(n的平方),不适合大数据集计算
DIANA算法
DIANA用到如下两个定义:
(1) 簇的直径:在一个簇中的任意两个数据点都有一个欧氏距离,这些距离中的最大值是簇的直径
(2) 平均相异度(平均距离):
算法描述:
输入:包含n个对象的数据库,终止条件簇的数目k
输出:k个簇,达到终止条件规定簇数目
(1) 将所有对象整个当成一个初始簇
(2) For ( i=1;i!=k;i++) Do Begin
(3) 在所有簇中挑选出具有最大直径的簇;
(4) 找出所挑出簇里与其他点平均相异度最大的一个点放入splinter group,剩余的放入old party中。
(5) Repeat
(6) 在old party里找出到splinter group中点的最近距离不大于old party中点的最近距离的点,并将该点加入splinter group
(7) Until 没有新的old party的点被分配给splinter group;
(8) Splinter group 和old party为被选中的簇分裂成的两个簇,与其他簇一起组成新的簇集合
(9) END
算法性能:
缺点是已做的分裂操作不能撤销,类之间不能交换对象。如果在某步没有选择好分裂点,可能会导致低质量的聚类结果。大数据集不太适用。
缺点:
传统的层次聚类算法的效率比较低 O(tn2 ) t: 迭代次数 n: 样本点数,最明显的一个缺点是不具有再分配能力,即如果样本点 A 在某次迭代过程中已经划分给类簇 C1 ,那么在后面的迭代过程中 A 将永远属于类簇 C1 ,这将影响聚类结果的准确性。
其他算法
层次聚类方法比较简单,但是经常遇到的一个问题,就是在合并或分裂点选择困难的问题。一个有希望的改进方向是将层级聚类和其他聚类技术进行集成,形成多阶段聚类。
(1) BIRCH算法
BIRCH(利用层次方法的平衡迭代规约和聚类)是一个总和的层次聚类方法,
(2) CURE算法
----------------贴上本人实现的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 dataPoints = new ArrayList(); // 类簇中的样本点
private String clusterName;
public List getDataPoints() {
return dataPoints;
}
public void setDataPoints(List 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 startAnalysis(List dataPoints,int ClusterNum){
List finalClusters=new ArrayList();
List 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 dataPointsA=clusterA.getDataPoints();
List dataPointsB=clusterB.getDataPoints();
for(int m=0;m mergeCluster(List clusters,int mergeIndexA,int mergeIndexB){
if (mergeIndexA != mergeIndexB) {
// 将cluster[mergeIndexB]中的DataPoint加入到 cluster[mergeIndexA]
Cluster clusterA = clusters.get(mergeIndexA);
Cluster clusterB = clusters.get(mergeIndexB);
List dpA = clusterA.getDataPoints();
List 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 clusters中移除cluster[mergeIndexB]
clusters.remove(mergeIndexB);
}
return clusters;
}
// 初始化类簇
private List initialCluster(List dataPoints){
List originalClusters=new ArrayList();
for(int i=0;i tempDataPoints=new ArrayList();
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 dpoints = new ArrayList();
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 clusters=ca.startAnalysis(dpoints, clusterNum);
for(Cluster cl:clusters){
System.out.println("------"+cl.getClusterName()+"------");
List tempDps=cl.getDataPoints();
for(DataPoint tempdp:tempDps){
System.out.println(tempdp.getDataPointName());
}
}
}
}