系统聚类思想及其Python实现

系统聚类是一种将对象或数据按照其相似性进行分组的方法。与传统聚类方法不同,系统聚类通过构建一颗层次树(或称为树状图或谱系图)来展现数据的层次结构。在系统聚类中,数据点最初被视为单独的簇,然后通过逐步合并或分裂,形成一个层次结构的聚类结果。这种层次结构可用于分析数据的不同层次的相似性关系。系统聚类常用于生物学、分类学、社会网络等领域,其中对于数据之间的演化或关联关系的理解十分重要。系统聚类的结果可通过树状图直观地展示,为研究者提供了对数据结构和组织的更深层次的认识。在进行机器学习时,往往要把相似的样品点/数据点进行归类,相似度高的样品点会放在一起,这样一个样本就会被分成几类。而聚类分析也有很多种方法,比如分解法、加入法、有序样品的聚类、模糊聚类法以及系统聚类法等。这里学习系统聚类法,以及如何用python来进行系统聚类分析。

一、系统聚类的思想

系统聚类法(hierarchical clustering method),又叫分层聚类法,是目前最常用的聚类分析方法。其基本步骤如下:假设样本中有n个样品,那么就先将这n个样品看作n类,也就是一个样品一个类,然后将性质最接近的两类合并为一个新的类,这样就得到n-1个类,接着从中再找出最接近的两个类,让其进行合并,这样就变为n-2个类,让此过程持续进行下去,最后所有的样品都归为一类,把上述过程绘制成一张图,这个图就称为聚类图,从图中再决定分为多少类。其大致过程如下图所示。

1.1 样本间的距离

  • 绝对值距离: d(xi,xj)=k=1p|xikxjk|
  • 欧式距离: d(xi,xj)=k=1p(xikxjk)2
  • Minkowski距离: d(xi,xj)=[k=1p(xikxjk)q]1q
  • Chebyshev距离: d(xi,xj)=max1kp|xikxjk|
  • 马氏距离: d(xi,xj)=(xi,xj)1(xi,xj)其中: xi=(xi1,xi2,,xip),xj=(xj1,xj2,,xjp)

1.2 类类间的距离

最短距离法(SINGLE):两类间距离的最小者

Dpq=miniGp,jGqdij

递推公式:

Drk=min{Dpk,Dqk}

系统聚类方法的递推公式可以统一为:

Drk2=αpDpk2+αqDqk2+βDpq2+γ|Dpk2Dqk2|

方法 αp αq β γ
最短距离法(single linkage method) 1/2 1/2 0 1/2
最长距离法(complete linkage method) 1/2 1/2 0 1/2
中间距离法(median method) 1/2 1/2 1/4 0
重心法(centroid hierarchical method) np/nr nq/nr αpαq 0
类平均法(Group average method) np/nr nq/nr 0 0
可变类平均 (1β)np/nr (1β)nq/nr β(<1) 0
可变法 (1β)/2 (1β)/2 β(<1) 0
离差平方和(ward method) (np+nk)/(nr+nk) (nq+nk)/(nr+nk) nk/(nk+nr) 0


二、系统聚类算例

2.1 聚类计算过程展示

根据五个学生的六门课的成绩,对这五个学生进行分类。

ID 数学 物理 化学 语文 历史 英语
1 65 61 72 84 81 79
2 77 77 76 64 70 55
3 67 63 49 65 67 57
4 80 69 75 74 74 63
5 74 70 80 84 81 74
  • 写出样本间的距离矩阵(以欧氏距离为例)
import numpy as np
from scipy.spatial.distance import pdist, squareform

# 给定的点集,每个点是一个包含6个数值的列表
points = np.array([
    [65, 61, 72, 84, 81, 79],  # A1
    [77, 77, 76, 64, 70, 55],  # A2
    [67, 63, 49, 65, 67, 57],  # A3
    [80, 69, 75, 74, 74, 63],  # A4
    [74, 70, 80, 84, 81, 74]   # A5
])

# 使用pdist计算所有点之间的距离
distances = pdist(points, 'euclidean')  # 使用欧几里得距离
# 使用squareform将一维的距离数组转换为方阵形式
distance_matrix = squareform(distances)
# 打印距离矩阵,数值保留两位小数
print(np.round(distance_matrix, 1))

D0=[038.9039.732.2026.515.932.4015.830.943.618.20]G1G2G3G4G5

  • 将每一个样本看做是一个类,即 G1,G2,G3,G4,G5 。观察 D(G1,G5)=15.8 最小,故将 G1G5 聚为一类,记为 G6。计算新类与其余各类之间的距离,得到新的距离矩阵D1。

D(G6,G2)=min{D(G1,G2),D(G5,G2)}=min{38.9,30.9}=30.9D(G6,G3)=min{D(G1,G3),D(G5,G3)}=min{39.7,43.6}=39.7D(G6,G4)=min{D(G1,G4),D(G5,G4)}=min{26.5,18.2}=18.2

D1=[030.9039.732.2018.215.932.40]G6G2G3G4

  • 观察 D(G2,G4)=15.9 最小,故将G2与G4聚为一类,记为 G7 。计算新类与其余各类之间的距离,得到新的距离矩阵 D2。

D(G7,G6)=min{D(G2,G6),D(G4,G6)}=min{30.9,18.2}=18.2D(G7,G3)=min{D(G2,G3),D(G4,G3)}=min{32.2,32.4}=32.2D2=[018.2032.239.70]G7G6G3

  • 观察 D(G6,G7)=18.2 最小,故将G6与G7聚为一类,记为 G8 。计算新类与其余各类之间的距离,得到新的距离矩阵 D3。

D(G8,G3)=min{D(G6,G3),D(G7,G3)}=min{39.7,32.2}=32.2

D3=[032.20]G8G3

  • 最后将 G8G3 聚为一类, 记为 G9

import numpy as np
from scipy.cluster.hierarchy import linkage, fcluster,dendrogram
from matplotlib import pyplot as plt

data = np.array([
    [65, 61, 72, 84, 81, 79],
    [77, 77, 76, 64, 70, 55],
    [67, 63, 49, 65, 67, 57],
    [80, 69, 75, 74, 74, 63],
    [74, 70, 80, 84, 81, 74]
])

# 计算链接矩阵(linkage matrix)
Z = linkage(data, method='centroid')
f = fcluster(Z, t=25, criterion='distance')

# 绘制树状图(dendrogram)
fig = plt.figure(figsize=(10, 7))
dn = dendrogram(Z)

# 显示图形
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('Sample index')
plt.ylabel('Distance')
plt.show()
# 打印链接矩阵Z,保留两位小数
print('Z:\n', np.round(Z, 2))
print('f:\n', f)

2.2 Python聚类函数详解

函数 作用 用法 参数
linkage linkage输出Z是包含聚类树信息的(n-1)×4矩阵(n表示样本数)。矩阵Z第1、2列表示被两两连接生成一个新类的对象索引;第3列表示两两对象的连接距离;第4列表示当前类中原始对象的个数。 Z = linkage(X, method='centroid') 第一个参数y为一个尺寸为(m,n)的二维矩阵。一共有n个样本,每个样本有m个维度。参数method =’single’:一范数距离;’complete’:无穷范数距离;’average’:平均距离;’centroid’:二范数距离;’ward’:离差平方和距离,返回值:(n-1)*4 的矩阵 Z
fcluster 这个函数压平(切割)树状图,根据距离阈值t——允许的最大簇间距离进行样本分配 f =fcluster(Z, scalar, criterion)=fcluster(Z, t=3, criterion='distance') 参数Z是linkage函数的输出Z;参数scalar:形成扁平簇的阈值t;参数criterion:’inconsistent’:预设的,如果一个集群节点及其所有后代的不一致值小于或等于t,那么它的所有叶子后代都属于同一个平面集群。’distance’:每个簇的距离不超过t;输出是每一个样本数据所在的类别。
dendrogram 展示层次聚类产生的树状图,以便更直观地理解数据点之间的聚类结构。 dendrogram(Z) 参数Z是linkage函数的输出Z,这个矩阵是一个二维数组,其中每一行代表一次合并操作,包含了被合并的两个组群的索引以及它们之间的距离。
import numpy as np
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram
from matplotlib import pyplot as plt

# 定义数据
X = np.array([[2], [8], [0], [4], [1], [9], [9], [0]])

# 计算链接矩阵
Z = linkage(X, method='centroid')

# 执行聚类
f = fcluster(Z, t=3, criterion='distance')

# 创建图形对象
fig = plt.figure(figsize=(5, 3))

# 绘制树状图
dn = dendrogram(Z)

# 打印链接矩阵Z,保留两位小数
print('Z:\n', np.round(Z, 2))
# 打印聚类结果f,保留两位小数(如果f中的数字需要格式化的话)
# 由于f是整数类型,通常不需要格式化小数位,但如果需要可以转换为浮点数并格式化
print('f:\n', f)

# 显示图形
plt.show()

程序中的链接矩阵看下表,Zij表示矩阵Z的第i行第j列:

i Zi0 Zi1 Zi2 Zi3 类别
0 2 7 0 2 8
1 5 6 0 2 9
2 0 4 1 2 10
3 8 10 1 4 11
4 1 9 1 3 12
5 3 11 2 5 13
6 12 13 4 8 14

表中行数据解析如下:

  • 索引2和7对应 0 和 0,二者距离为 0,并且组成一个新的类,编号为8。
  • 索引5和6对应 9 和 9,二者距离为 0,组成新类,编号为9。
  • 索引0和4对应 2 和 3,二者距离为 1,组成新类,编号为10。
  • 3和8对应 4 和 { 2:0,7:0 },类间距离为 2,组成新类,编号为11。
  • ……以此类推

三、系统聚类案例的Python实现

import pandas as pd
from scipy.cluster.hierarchy import linkage, fcluster, dendrogram
import matplotlib.pyplot as plt

# 读取 country.csv 文件,见文中最后数据文件结构
X = pd.read_csv('country.csv', encoding='utf-8')

# 选择只包含数值型数据的列
numeric_cols = X.select_dtypes(include=['number']).columns
X_numeric = X[numeric_cols]

# 进行层次聚类
Z = linkage(X_numeric, method='ward')  # 选择层次聚类的方法,这里使用Ward方法

#通过树状图可视化层次聚类结果
plt.figure(figsize=(15, 8))
dendrogram(Z)
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('Sample Index')
plt.ylabel('Distance')
plt.show()

#根据树状图的切割高度,确定聚类簇的数量
cut_height = 300  # 根据实际情况调整
clusters = fcluster(Z, t=cut_height, criterion='distance')

#输出聚类结果
X['Cluster'] = clusters
print(X.head())
流程图 系统聚类图

四、系统聚类练习案例

城市 乡村劳动力资源(人) 农用机械总动力(千瓦) 农村用电量(万千瓦小时) 农村社会总产值(万元) 自来受益村(个) 通电村数(个) 有效灌溉面积(公顷) 农村运输业固定资产(万元)
石家庄 3849814 19001804 624877 37574543 3980 4418 495628 525146
唐山 3175708 9317581 1169791 48736085 3785 5020 499068 547760
秦皇岛 1201891 2782741 113192 6792279 847 2262 124364 138657
邯郸 3691615 12068651 448244 36969131 4590 5347 535707 435227
邢台 2992865 8278320 241519 21763646 4954 5172 553587 379118
保定 5446331 10247700 321625 28093014 4116 6210 655113 431368
张家口 1945917 2415071 68599 6484145 2863 4067 249021 159708
承德 1743264 2114710 121829 9254893 1620 2552 138738 182419
沧州 3212666 10811991 537227 34369166 5679 5741 561042 332882
廊坊 1706083 6467986 386814 23224066 3164 3222 283788 280718
衡水 1895102 7838729 267634 15258973 4933 4982 473719 138165

总结

系统聚类方法是一种将数据按照层次结构进行分组的聚类技术。其基本思想是通过构建一颗层次树,根据数据点之间的相似性逐步合并或分裂簇,形成层次化的聚类结果。系统聚类方法在生物学、分类学、社会网络分析等领域有广泛应用。在生物学中,系统聚类可用于分析物种的进化关系,揭示基因或蛋白质的功能相似性。在分类学中,它帮助研究者理解不同类别之间的关系。在社会网络分析中,系统聚类揭示了不同社群之间的联系,有助于理解网络结构和社会组织。系统聚类方法通过提供层次结构的视角,使得对数据的更深入理解成为可能,为各个领域的研究提供了有力工具。

参考文献

  1. 系统(层次)聚类原理详解及案例分析
  2. 层次聚类法应用实例及Python实现
  3. 原理+代码|详解层次聚类及Python实现
  4. 层次聚类python,scipy(dendrogram, linkage,fcluster函数)

用层次聚类法对世界20个国家和地区进行聚类,具体数据country.csv如下:

country call movecall fee computer mips net
1 美 国 631.60 161.90 0.36 403.00 26073.00 35.34
2 日 本 498.40 143.20 3.57 176.00 10223.00 6.26
3 德 国 557.60 70.60 2.18 199.00 11571.00 9.48
4 瑞 典 684.10 281.80 1.40 286.00 16660.00 29.39
5 瑞 士 644.00 93.50 1.98 234.00 13621.00 22.68
6 丹 麦 620.30 248.60 2.56 296.00 17210.00 21.84
7 新加坡 498.40 147.50 2.50 284.00 13578.00 13.49
8 中国台湾 469.40 56.10 3.68 119.00 6911.00 1.72
9 韩 国 434.50 73.00 3.36 99.00 5795.00 1.68
10 巴 西 81.90 16.30 3.02 19.00 876.00 0.52
11 智 利 138.60 8.20 1.40 31.00 1411.00 1.28
12 墨西哥 92.20 9.80 2.61 31.00 1751.00 0.35
13 俄罗斯 174.90 5.00 5.12 24.00 1101.00 0.48
14 波 兰 169.00 6.50 3.68 40.00 1796.00 1.45
15 匈牙利 262.20 49.40 2.66 68.00 3067.00 3.09
16 马来西亚 195.50 88.40 4.19 53.00 2734.00 1.25
17 泰 国 78.60 27.80 4.95 22.00 1662.00 0.11
18 印 度 13.60 0.30 6.28 2.00 101.00 0.01
19 法 国 559.10 42.90 1.27 201.00 11702.00 4.76
20 英 国 521.10 122.50 0.98 248.00 14461.00 11.91
posted @   郝hai  阅读(683)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示