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 ...
随机推荐
- Hibernate逍遥游记-第12章 映射值类型集合-004映射Map(<map-key>)
1. 2. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate ...
- C++:this指针
this指针 this关键字:表示本类中的对象成员,可以通过this指针访问当前类的成员//举例 //例 3.18 隐藏this指针的引例 #include<iostream> using ...
- PCL—综述—三维图像处理
点云模型与三维信息 三维图像是一种特殊的信息表达形式,其特征是表达的空间中三个维度的数据.和二维图像相比,三维图像借助第三个维度的信息,可以实现天然的物体-背景解耦.除此之外,对于视觉测量来说,物体的 ...
- 转Struts 权限控制
权限最核心的是业务逻辑,具体用什么技术来实现就简单得多. 通常:用户与角色建立多对多关系,角色与业务模块构成多对多关系,权限管理在后者关系中. 对权限的拦截,如果系统请求量大,可以用Struts2拦截 ...
- Hibernate 主键策略
Hibernate主键生成策略 .自动增长identity 适用于MySQL.DB2.MS SQL Server,采用数据库生成的主键,用于为long.short.int类型生成唯一标识 使用SQL ...
- mongodb group分组
先插入测试数据: for(var i=1; i<20; i++){ var num=i%6; db.test.insert({_id:i,name:"user_&quo ...
- Android 下log的使用总结
Android 下log的使用总结 一:在源码开发模式下 1:包含头文件: #include <cutils/log.h> 2:定义宏LOG_TAG #define LOG_TAG &qu ...
- Androidz之Activity概要学习
Androidz之Activity概要学习 1. Activity类概述 Activity(活动)是一个单独的.能获取焦点的,且能与用户交互的东西.所以我们通常在Activity类中的onCr ...
- uvaIrrelevant Elements
唯一分解定理. 可以看出在最后每个a的系数是杨辉三角的第n行. 但是不能递推,否则会tle. 就从C(n-1,0)开始乘n-k再除以k.记录下每个的系数,如果该项系数小于m就代表和答案有关. 代码里的 ...
- UVa 10883 (组合数 对数) Supermean
在纸上演算一下就能看出答案是:sum{ C(n-1, i) * a[i] / 2^(n-1) | 0 ≤ i ≤ n-1 } 组合数可以通过递推计算:C(n, k) = C(n, k-1) * (n- ...