层次聚类是另一种主要的聚类方法,它具有一些十分必要的特性使得它成为广泛应用的聚类方法。它生成一系列嵌套的聚类树来完成聚类。单点聚类处在树的最底层,在树的顶层有一个根节点聚类。根节点聚类覆盖了全部的所有数据点。层次聚类分为两种:

  • 合并(自下而上)聚类(agglomerative)
  • 分裂(自上而下)聚类(divisive)

目前 使用较多的是合并聚类 ,本文着重讲解合并聚类的原理。

Agens层次聚类原理

合并聚类主要是将N个元素当成N个簇,每个簇与其 欧氏距离最短 的另一个簇合并成一个新的簇,直到达到需要的分簇数目K为止,示意图如下:

举个例子,作者将26个字母随机分配了坐标(x,y),如:

# {'K': {'y': 34, 'x': 81}, 'V': {'y': 68, 'x': 50}, 'G': {'y': 1, 'x': 10}, 'C': {'y': 2, 'x': 9}, 'T': {'y': 78, 'x': 40}, 'A': {'y': 20, 'x': 12}, 'B': {'y': 21, 'x': 39}, 'N': {'y': 37, 'x': 67}, 'S': {'y': 92, 'x': 56}, 'Q': {'y': 7, 'x': 62}, 'D': {'y': 18, 'x': 4}, 'E': {'y': 0, 'x': 38}, 'Z': {'y': 92, 'x': 46}, 'H': {'y': 30, 'x': 32}, 'I': {'y': 21, 'x': 35}, 'U': {'y': 71, 'x': 51}, 'L': {'y': 1, 'x': 96}, 'W': {'y': 99, 'x': 59}, 'F': {'y': 10, 'x': 14}, 'O': {'y': 16, 'x': 97}, 'J': {'y': 37, 'x': 76}, 'X': {'y': 86, 'x': 49}, 'Y': {'y': 67, 'x': 50}, 'P': {'y': 17, 'x': 76}, 'M': {'y': 32, 'x': 88}, 'R': {'y': 6, 'x': 70}}

点的位置如下:

  • 假设要分成1个簇,即 K=1 ,那么平面上的所有点都在一起,如下图红色点:

  • 假设要分成2个簇,即 K=2 ,则根据 欧式距离 公式,首先将字母分成了红色的点和绿色的点,黑色的点为未分配:

而黑色的点可能一部分与红色的点距离较近,所以一部分变成了红色,一部分变成了绿色:

  • 假设要分成3个簇,即 K=3 ,如下图红色、绿色、紫色的点:

假设 K=3 ,合并的步骤为:

  1. 26个字母首先被分配成 26 个簇
  2. 两两欧氏距离最近的两个簇合并,此时簇变成了 13
  3. 再次两两欧氏距离最近的两个簇合并,此时一共有 12 个簇合并成了6个簇,还余下一个簇,因此此时剩下 6+1=7 个簇
  4. 一直重复上一步的操作,直到簇的数量为 3 的时候,就算是分簇完成

Agens层次聚类实现:

  • 随机生成26个字母:
# 生成坐标字典
def buildclusters():
clusters = {}
keys = [chr(i) for i in range(ord('A'), ord('Z') + 1)]
# ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# 生成第一个分簇坐标
for i in range(0, 9):
# A-I
temp = {}
x = random.randint(0, 40)
y = random.randint(0, 40)
temp["x"] = x
temp["y"] = y
clusters[keys[i]] = temp # 生成第二个分簇坐标
for i in range(9, 18):
# J-R
temp = {}
x = random.randint(60, 100)
y = random.randint(0, 40)
temp["x"] = x
temp["y"] = y
clusters[keys[i]] = temp # 生成第三个分簇坐标
for i in range(18, 26):
# S-Z
temp = {}
x = random.randint(40, 60)
y = random.randint(60, 100)
temp["x"] = x
temp["y"] = y
clusters[keys[i]] = temp return clusters

得到的结果为:

{'K': {'y': 34, 'x': 81}, 'V': {'y': 68, 'x': 50}, 'G': {'y': 1, 'x': 10}, 'C': {'y': 2, 'x': 9}, 'T': {'y': 78, 'x': 40}, 'A': {'y': 20, 'x': 12}, 'B': {'y': 21, 'x': 39}, 'N': {'y': 37, 'x': 67}, 'S': {'y': 92, 'x': 56}, 'Q': {'y': 7, 'x': 62}, 'D': {'y': 18, 'x': 4}, 'E': {'y': 0, 'x': 38}, 'Z': {'y': 92, 'x': 46}, 'H': {'y': 30, 'x': 32}, 'I': {'y': 21, 'x': 35}, 'U': {'y': 71, 'x': 51}, 'L': {'y': 1, 'x': 96}, 'W': {'y': 99, 'x': 59}, 'F': {'y': 10, 'x': 14}, 'O': {'y': 16, 'x': 97}, 'J': {'y': 37, 'x': 76}, 'X': {'y': 86, 'x': 49}, 'Y': {'y': 67, 'x': 50}, 'P': {'y': 17, 'x': 76}, 'M': {'y': 32, 'x': 88}, 'R': {'y': 6, 'x': 70}}
  • 欧氏距离公式:
# 两点间的距离公式/欧式距离
def distance(x1, x2, y1, y2):
distan = ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
return distan
  • 第一次分簇:
# 计算各个分簇直到达到分簇的效果
def splitcluster(clusters):
dict = {}
newdict = {}
arr = []
i = 1
for key1 in clusters:
temp = {}
for key2 in clusters:
if key1 != key2:
if key1 in arr or key2 in arr:
pass
else:
name = str(key1 + "->" + key2)
temp[name] = distance(clusters[key1]["x"], clusters[key2]["x"], clusters[key1]["y"],
clusters[key2]["y"])
arr.append(key1)
arr.append(key2) if temp:
# reverse=False值按照从小到大排序
temp = sorted(temp.items(), key=lambda d: d[1], reverse=False)
newdict[temp[0][0]] = temp[0][1] newdict = sorted(newdict.items(), key=lambda d: d[1], reverse=False)
for item in newdict:
name = "cluster" + str(i)
i += 1 dict[name] = item[0] return dict

成功的将其分成13个簇,得到的结果为:

{'cluster13': 'B->T', 'cluster11': 'U->M', 'cluster10': 'Z->H', 'cluster5': 'L->D', 'cluster1': 'F->E', 'cluster4': 'G->A', 'cluster12': 'I->S', 'cluster3': 'W->V', 'cluster8': 'C->R', 'cluster9': 'P->X', 'cluster2': 'K->N', 'cluster7': 'O->Q', 'cluster6': 'Y->J'}
  • 迭代分簇,直到满足K为止:
# 判断分簇
def judgecluster(clusters, firstcluster, K):
dict = {}
i = 1
arr = []
for item in firstcluster:
temparr = firstcluster[item].split("->")
distan = {}
for judge in temparr:
if judge in arr:
pass
else:
for value in clusters:
if value in temparr:
pass
elif value in arr:
pass
else:
for key in temparr:
name = value + "->" + key
distan[name] = distance(clusters[key]["x"], clusters[value]["x"], clusters[key]["y"],
clusters[value]["y"])
if key in arr:
pass
else:
arr.append(key)
if distan:
distan = sorted(distan.items(), key=lambda d: d[1], reverse=False)
# print(distan)
element = distan[0][0].split("->")[0]
for ele in firstcluster:
elearr = firstcluster[ele].split("->")
if element in elearr:
values = firstcluster[item]
for va in elearr:
values = values + "->" + va
arr.append(va)
cluster = "cluster" + str(i)
i += 1
dict[cluster] = values if len(arr) != 26:
# 生成26个字母
letters = [chr(i) for i in range(ord('A'), ord('Z') + 1)]
# 得到剩下没有被放到dict的字母
remain = []
for letter in letters:
if letter in arr:
pass
else:
remain.append(letter)
dis = {}
for letter in remain:
for item in dict:
elearr = dict[item].split("->")
for ele in elearr:
name = letter + "->" + ele
dis[name] = distance(clusters[letter]["x"], clusters[ele]["x"], clusters[letter]["y"],
clusters[ele]["y"])
if dis:
dis = sorted(dis.items(), key=lambda d: d[1], reverse=False)
element = dis[0][0].split("->") for cluster in dict:
array = dict[cluster].split("->")
for item in element:
if item in array:
values = "->".join(remain)
dict[cluster] = dict[cluster] + "->" + values if len(dict) == K:
print(dict)
# {'cluster1': 'M->X->P->Y->J->U->T->R->L->O', 'cluster3': 'V->B->W->N->E->A->I->G', 'cluster2': 'C->H->Q->F->D->S->Z->K'}
return dict
else:
judgecluster(clusters, dict, K)

本文选取的 K=3 ,最后得到的结果为:

{'cluster1': 'M->X->P->Y->J->U->T->R->L->O', 'cluster3': 'V->B->W->N->E->A->I->G', 'cluster2': 'C->H->Q->F->D->S->Z->K'}

由此可见,按照这个结果,作者手动画的图是错误的...

python代码在我的博客上面:

TTyb

Agens层次聚类的更多相关文章

  1. 挑子学习笔记:BIRCH层次聚类

    转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/6129425.html 本文是“挑子”在学习BIRCH算法过程中的笔记摘录,文中不乏一些个人理解,不当之处望 ...

  2. 2.交通聚类 -层次聚类(agnes)Java实现

    1.项目背景 在做交通路线分析的时候,客户需要找出车辆的行车规律,我们将车辆每天的行车路线当做一个数据样本,总共有365天或是更多,从这些数据中通过聚类来获得行车路线规律统计分析. 我首先想到是K-m ...

  3. 聚类算法:K均值、凝聚层次聚类和DBSCAN

    聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不 ...

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

    网上教程太啰嗦,本人最讨厌一大堆没用的废话,直接上,就是干! 网络爬虫?非监督学习? 只有两步,只有两个步骤? Are you kidding me? Are you ok? 来吧,follow me ...

  5. 机器学习(六)K-means聚类、密度聚类、层次聚类、谱聚类

    本文主要简述聚类算法族.聚类算法与前面文章的算法不同,它们属于非监督学习. 1.K-means聚类 记k个簇中心,为\(\mu_{1}\),\(\mu_{2}\),...,\(\mu_{k}\),每个 ...

  6. 机器学习算法总结(五)——聚类算法(K-means,密度聚类,层次聚类)

    本文介绍无监督学习算法,无监督学习是在样本的标签未知的情况下,根据样本的内在规律对样本进行分类,常见的无监督学习就是聚类算法. 在监督学习中我们常根据模型的误差来衡量模型的好坏,通过优化损失函数来改善 ...

  7. 【层次聚类】python scipy实现

    层次聚类 原理 有一个讲得很清楚的博客:博客地址 主要用于:没有groundtruth,且不知道要分几类的情况 用scipy模块实现聚类 参考函数说明: pdist squareform linkag ...

  8. 常见聚类算法——K均值、凝聚层次聚类和DBSCAN比较

    聚类分析就仅根据在数据中发现的描述对象及其关系的信息,将数据对象分组(簇).其目标是,组内的对象相互之间是相似的,而不同组中的对象是不同的.组内相似性越大,组间差别越大,聚类就越好. 先介绍下聚类的不 ...

  9. ML: 聚类算法R包-层次聚类

    层次聚类 stats::hclust stats::dist    R使用dist()函数来计算距离,Usage: dist(x, method = "euclidean", di ...

随机推荐

  1. RESTful-3架构详解

    1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fielding的 ...

  2. Final Cut Pro X for Mac(FCPX专业视频剪辑工具)实用技巧篇!

    Final Cut Pro X for Mac是一款非常强大的专业视频剪辑工具,全球很多人都在用!现在小编给大家带来一些关于Final Cut Pro X for Mac的使用技巧,希望对大家以后的应 ...

  3. XYZZY spfa 最长路 判环

    题意: 有n个点  m条边  每个边有权值 一开始有一百血  每次经过一条路都会加上其权值 判断是否能够到达n 显然  有正环的时候肯定能够到达 最短路好题!!!!!!! 显用folyed判断是否联通 ...

  4. Linux-day2-上课笔记

    UGO权限 1) 文件对于拥有者的权限   User 2) 文件对于所属组里面的用户的权限 Group 3) 文件对于其他人的权限  Others 对于文件的权限 1)对于文件可读  r 2)对于文件 ...

  5. Go语言初篇

    Go语言初篇 目录 Go-开发环境 Go-语言基础 Go-标准库 Go-面向对象 Go-并发 Go-数据库 Go-web框架 Go语言开发文档:https://studygolang.com/pkgd ...

  6. linux环境下安装tcping工具测试访问超时

    wget https://sources.voidlinux.eu/tcping-1.3.5/tcping-1.3.5.tar.gz tar zxvf tcping-1.3.5.tar.gz cd t ...

  7. GitHub的简单使用记录

    记录于:2013/4/24 GitHub(网址 https://github.com/)是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub.   G ...

  8. MyBatis3系列__02接口式编程

    hello world MyBatis3支持面向接口编程: 具体做法如下,将helloWorld中的EmployeeMapper.xml文件进行更改: <?xml version="1 ...

  9. VMware ESXi 6.5 安装

    1.1下载esxi镜像 此处我使用的版本是:VMware-VMvisor-Installer-6.5.0-4564106.x86_64 1.2新建一个虚拟机,硬件兼容性处选择ESXI6.5 硬盘40g ...

  10. linux的一些基础命令

    Linux是基于Unix的开源免费的操作系统,是部署服务器的很好选择. 系统:win10 工具:vm虚拟机+Xshell/CRT  虚拟机的系统为linux centos 7 首先看一下linux的基 ...