Hierarchical cluster算法介绍
突然想记录几个聚类算法,由于实力有限就先介绍一下层次聚类算法(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算法介绍的更多相关文章
- matlab下K-means Cluster 算法实现
一.概念介绍 K-means算法是硬聚类算法,是典型的局域原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则.K-means算法以欧 ...
- k-means|k-mode|k-prototype|PAM|AGNES|DIANA|Hierarchical cluster|DA|VIF|
聚类算法: 对于数值变量,k-means eg:k=4,则选出不在原数据中的4个点,计算图形中每个点到这四个点之间的距离,距离最近的便是属于那一类.标准化之后便没有单位差异了,就可以相互比较. 对于分 ...
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...
- KNN算法介绍
KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...
- ISP基本框架及算法介绍
什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...
- Python之常见算法介绍
一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...
- RETE算法介绍
RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...
- H2O中的随机森林算法介绍及其项目实战(python实现)
H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...
- STL 算法介绍
STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成. <algorithm ...
随机推荐
- 解决不安装VC运行库(VC2005,VC2008),程序运行出错的方法
因为VS2005以后程序采用了manifest的生成方式,所以发布的时候要和运行库一起发布.但是我们平时开发和发布的时候如果都要客户安装运行库,那就不太方便了.你可以Microsoft下载:http: ...
- Use Eclipse to develop groovy[docs.codehaus.org]
http://docs.codehaus.org/display/GROOVY/Install+Groovy-Eclipse+Plugin http://docs.codehaus.org/displ ...
- apache prefork和worker模式的比较
http://www.t086.com/article/4443 http://www.cnblogs.com/fnng/archive/2012/11/20/2779977.html
- Windows 7更改SVN账户密码
首先说明下我的系统是Windows7 今天更改了SVN账号和密码,然后想要更改一下Eclipse的SVN登录用户名和密码 但是网上找了一大推说什么客户端的,靠净扯淡. 本人亲测最有效的方法是删除C盘下 ...
- java 菱形
//画菱形 一半 for(int hs=1;hs<11;hs++) //行数 { //画空格 for(int kg = 9; kg >= hs; kg--) //空格数 { System. ...
- [HDOJ2818]Building Block(带权并查集,路径压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2818 题意:有N个块,每次有两个操作: M x y表示把x所在的那一堆全部移到y所在的那一堆的下方. ...
- SQL server函数大全
函数类别 作用 聚合函数 执行的操作是将多个值合并为一个值.例如 COUNT.SUM.MIN 和MAX. 配置函数 是一种标量函数,可返回有关配置设置的信息. 转换函数 将值从一种数据类型转换为另一种 ...
- bzoj4080
分组赛时wy大神讲的题,网上都是随机化的题解 我来讲一下正解吧,我们穷举两个点,这两点距离要小于限制 然后我们分别以这两个点为圆心,两点距离为半径画圆 圆圆相交的部分被两点练成线段划分成两部分,不难发 ...
- POJ 1276 (多重背包) Cash Machine
题意: 有n种纸币,已知每种纸币的面值和数量,求所能凑成的不超过cash的最大总面值. 分析: 这道题自己写了一下TLE了,好可耻.. 找了份比较简洁的代码抄过来了..poj1276 #include ...
- HDU 2087 (KMP不可重叠的匹配) 花布条
题意: 用两个字符串分别表示布条和图案,问能从该布条上剪出多少这样的图案. 分析: 毫无疑问这也是用KMP匹配,关键是一次匹配完成后,模式串应该向后滑动多少. 和上一题 HDU 1686 不同,两个图 ...