突然想记录几个聚类算法,由于实力有限就先介绍一下层次聚类算法(Hierarchical cluster algorithm),这个聚类算法思想简单,但实现起来感觉复杂度挺大;以前看过《集体智慧编程》里介绍过,里面是用python实现的,由于python里面的列表和字典用起来方便,故实现该算法还行;这里我用c++重新写了一下,感觉代码蛮臃肿,可能是自己的c++没有学习好吧!!!对于容器的使用还不够熟练,这里贴出来的目的是希望哪位大牛看到了指导一二,这里感激不尽。废话不多说了,进入正题吧!

************************************************************************************************************

Hierarchical cluster Algorithm的大致介绍

  层次聚类算法有两种实现思想,一种是初始时将每个待聚类的数据样本视为一个cluster,采用合并的方式,每次合并两个"距离"最近的cluster,直到合并成一个cluster为止(当然可以在达到自己设定想得到的cluster个数时终止迭代);另一种刚好与第一种相反,初始时将所有的数据样本视为一个cluster,采用分解的方式(这里没有实现就不说太多)。

************************************************************************************************************

算法的步骤及相关问题

  算法步骤:  (1)初始时,将每个数据样本视为一个cluster(选取一个度量两个cluster距离的方式),

       (2)计算任意两个cluster之间的距离;每次选取距离最小的两个cluster,

       (3)合并(2)中选择的两个cluster,将合并产生的新cluster加入cluster set中,并删除被合并的两个cluster,

       (4)重复(2)(3),知道cluster set中元素只剩下一个为止。

  相关问题: (1)度量两个cluster之间的距离,应该选择哪种距离???《集体智慧编程》中选择的是Pearson,当然也可以直接选用欧氏距离

        (2)如何合并两个cluster,即新的cluster对应的属性值如何表示???这里是用被合并的两个cluster的平均值表示新的cluster

******************************************************************************************************************

 /**
** Hierarchical cluster Algorithm
** step:(1)Firstly,regard each sample as a cluster, and
(2)Each time merge two clusters if the distance between them is lowest.
(3)then add the new cluster into cluster set, and delete two clusters merged from cluster set.
** method: (1)as to merging, here replace the old two clusters with their average;
(2)measure the distance with the Pearson similarity.
** Time:2013/7/10
**/
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <cstring>
#include <sstream>
#include <cmath>
#include <iterator>
using namespace std;
//cluster
typedef struct bicluster{
vector<double> attri;//attribute
int cid;//cluster id
}Bicluster;
//a pair
typedef struct lowpair{
int leftid;
int rightid;
double dist;
}Lpair; /*****************************************************************
** convert string(char*) to double(or other type)
** here should be included <sstream> before using the stringstream
******************************************************************/
double str2double(char* str){
stringstream ss;
ss << str;
double tmp;
ss >> tmp;
return tmp;
}
/*****************************************************************
** split the string containing some special tokens
******************************************************************/
string split(string &str, vector<double>& dvec, const char* tok){
char *pch = NULL;
pch = strtok(const_cast<char*>(str.c_str()), tok);
string stmp(pch);
while( pch != NULL ){
pch = strtok(NULL, tok);
if( !pch )
break;
dvec.push_back(str2double(pch));
}
return stmp;
}
/******************************************************************
** read data from 'blogdata.txt'
** @is ------- a reference to ifstream object(input)
** @data ----- a map used to store the data (output)
******************************************************************/
bool readfile(ifstream &is, map<string, vector<double> >& mydata){
if( is.fail() ){
cerr << "can't open the file !!!" << endl;
return false;
}
//ignore the first line of file
string str;
getline(is, str); //store the data read from file into mydata
while( !is.eof() ){
vector<double> dtmp;
string tmp;
getline(is, str);
tmp = split(str, dtmp, "\t");
mydata.insert(pair<string,vector<double> >(tmp, dtmp));
}
return true;
}
/*****************************************************************
** compute the distance between two clusters
** Note that Pearson value devotes to the similarity between
two clusters, that is, the greater the Pearson value, the
lower the distance between them.
*****************************************************************/
double distPearson(vector<double>& left, vector<double>& right){
double sum1 = ;
double sum2 = ;
int len = left.size();
for(int i=; i<len; ++i){
sum1 += left[i];
sum2 += right[i];
} /**
** maybe you will feel it's complex,
** and here we could replace Pearson with Euclidean distance
**/
double sum1Sq = ;
double sum2Sq = ;
for(int j=; j<len; ++j){
sum1Sq += pow(left[j], );
sum2Sq += pow(right[j], );
} double pSum = , num, den;
for(int k=; k<len; ++k)
pSum += left[k]*right[k];
num = pSum - sum1*sum2 / len;
den = sqrt((sum1Sq - pow(sum1,)/len) * (sum1Sq - pow(sum2,)/len));
if( den == )
return ;
return 1.0 - num/den;
}
/*************************************************************
** Given two clusters, the distance between them
should be checked whether it exists before compute it.
**************************************************************/
bool isExist(vector<Lpair> &lp, int leftid, int rightid, double &d){
vector<Lpair>::iterator it = lp.begin();
for(; it!=lp.end(); ++it){
if( (it->leftid==leftid) && (it->rightid==rightid) ){
d = it->dist;//if the distance has been computed, assign its value to d
return true;
}
}
d = ;
return false;
}
/*************************************************************
** Given a cluster's id, delete the cluster from cluster set
**************************************************************/
void Del(vector<Bicluster> &cvec, int clusterid){
vector<Bicluster>::iterator it = cvec.begin();
for(; it!=cvec.end(); ++it){
if( it->cid == clusterid )
break;
}
cvec.erase(it);
}
/*************************************************************
** Hierarchical Cluster Algorithm
**************************************************************/
void HierarchicalCluster(map<string, vector<double> > &mydata){
vector<Lpair> distances;//used to store the distance //firstly,regard each sample as a cluster
vector<Bicluster> cvec;
map<string, vector<double> >::iterator it = mydata.begin();
int myid = ;
for(; it!= mydata.end(); ++it){
Bicluster btmp;
btmp.attri = it->second;
btmp.cid = myid++;
cvec.push_back(btmp);
}
myid = -;
//search the pair
while( cvec.size()> ){
Lpair lowp;
double closedis = distPearson(cvec[].attri,cvec[].attri);
lowp.leftid = cvec[].cid, lowp.rightid = cvec[].cid;
lowp.dist = closedis; int leftps = , rightps = ;
for(int ix=; ix<cvec.size(); ++ix){
for(int iy=ix+; iy<cvec.size(); ++iy){
double d;
int lid = cvec[ix].cid, rid = cvec[iy].cid;
if( !isExist(distances,lid,rid,d) ){
Lpair lptmp;
lptmp.dist = distPearson(cvec[ix].attri, cvec[iy].attri);
lptmp.leftid = lid;
lptmp.rightid= rid;
distances.push_back(lptmp);
d = lptmp.dist;
}
if( d < lowp.dist ){
lowp.leftid = lid;
lowp.rightid = rid;
leftps = ix;
rightps = iy;
lowp.dist = d;
}
}
}
//create a new cluster
Bicluster ncluster;
for(int i=; i<cvec[].attri.size(); ++i){
double av;
av = (cvec[leftps].attri[i] + cvec[rightps].attri[i]) / 2.0;
ncluster.attri.push_back(av);
}
ncluster.cid = myid--;//assign negative to the new cluster's id
cout << "leftid: " << lowp.leftid << ", rightid: " << lowp.rightid << endl;
//delete the pair
Del(cvec, lowp.leftid);
Del(cvec, lowp.rightid);
cvec.push_back(ncluster);
}
}
int main()
{
ifstream is("blogdata.txt");
if( is.fail() ){
cerr << "error!!!" << endl;
exit(-);
}
map<string, vector<double> > mydata;
if(readfile(is, mydata))
HierarchicalCluster(mydata);
return ;
}

  代码写的有点乱且复杂,最后显示的结果不是树状图(python很易实现),只是简单的显示了每次被合并的两个cluster的id.代码中用到的数据可以从http://kiwitobes.com/clusters/blog.txt下载得到。

Hierarchical cluster算法介绍的更多相关文章

  1. matlab下K-means Cluster 算法实现

    一.概念介绍 K-means算法是硬聚类算法,是典型的局域原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则.K-means算法以欧 ...

  2. k-means|k-mode|k-prototype|PAM|AGNES|DIANA|Hierarchical cluster|DA|VIF|

    聚类算法: 对于数值变量,k-means eg:k=4,则选出不在原数据中的4个点,计算图形中每个点到这四个点之间的距离,距离最近的便是属于那一类.标准化之后便没有单位差异了,就可以相互比较. 对于分 ...

  3. 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍

    考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...

  4. KNN算法介绍

    KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...

  5. ISP基本框架及算法介绍

    什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...

  6. Python之常见算法介绍

    一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...

  7. RETE算法介绍

    RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...

  8. H2O中的随机森林算法介绍及其项目实战(python实现)

    H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...

  9. STL 算法介绍

    STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.        <algorithm ...

随机推荐

  1. 用 React 编写SVG图表

    1.代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="U ...

  2. VIM树状文件列表NERDTree

    下载和配置 NERDTree插件的官方地址如下,可以从这里获取最新的版本 https://github.com/scrooloose/nerdtree 下载zip安装包 或者使用下面官网源文件安装方法 ...

  3. Quartz任务调度快速入门

    Quartz任务调度快速入门 概述 了解Quartz体系结构 Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器.任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的 ...

  4. 80. Remove Duplicates from Sorted Array II

    题目: Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For ex ...

  5. C++:类模板与模板类

    6.3 类模板和模板类 所谓类模板,实际上是建立一个通用类,其数据成员.成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表.使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从 ...

  6. MyEclipse 从数据库反向生成Hibernate实体类

    第一个大步骤 window-->open Perspective-->MyEclipse Java Persistence 进行了上面的 操作后会出现一个视图DB Brower:MyEcl ...

  7. 让Maven支持代理

    1.如果你的公司架设了防火墙并设置了HTTP代理服务器来禁止你们直接连接互联网,那么Maven就无法通过代理自动下载依赖包. 为了让Maven能够工作,你需要在Maven的配置文件 settings. ...

  8. linux用VSFTP搭建FTP服务器

    一般在各种linux的发行版中,默认带有的ftp软件是vsftp,从各个linux发行版对vsftp的认可可以看出,vsftp应该是一款不错的ftp软件. sudo apt-get install v ...

  9. 2014图灵技术图书最受欢迎TOP15

    来自:图灵社区昨晚给我发的邮件,感觉不错,和大家分享,mark下. [小编语] 回首2014,感谢小伙伴们一路相随.让我们2015一起更快乐地玩耍.今天小编为大家盘点一下过去2014年表现最给力的技术 ...

  10. linux中压缩与解压缩命令小结

    linux中压缩与解压操作非常常见,其命令参数也非常的多,这里只介绍最经常用的带打包文件的几种压缩和解压方式和几个最常用的参数. 现在最常用的压缩和解压工具是gzip和bzip2,这两种工具不能相互解 ...