• 层次聚类分析


    1、python语言

    1. from scipy.cluster import hierarchy # 导入层次聚类算法
    2. import matplotlib.pylab as plt
    3. import numpy as np
    4. # 生成示例数据
    5. np.random.seed(0)
    6. data = np.random.random((20,1))
    7. # 使用树状图找到最佳聚类数
    8. Z = hierarchy.linkage(data,method='weighted',metric='euclidean')
    9. re = hierarchy.dendrogram(Z,color_threshold=0.2,above_threshold_color='#bcbddc')
    10. # 输出节点标签
    11. print(re["ivl"])
    12. # 画图
    13. plt.title('Dendrogram') # 标题
    14. plt.xlabel('Customers') # 横标签
    15. plt.ylabel('Euclidean distances') # 纵标签
    16. plt.show()

    dendrogram函数参数

    1. Z:层次聚类的结果,即通过scipy.cluster.hierarchy.linkage()函数计算得到的链接矩阵。
    2. p:要显示的截取高度(y轴的阈值),可以用于确定划分群集的横线位置。
    3. truncate_mode:指定截取模式。默认为None,表示不截取,可以选择 'lastp''mlab' 来截取显示。
    4. labels:数据点的标签,以列表形式提供。
    5. leaf_font_size:叶节点的字体大小。
    6. leaf_rotation:叶节点的旋转角度。
    7. show_leaf_counts:是否显示叶节点的数量。
    8. show_contracted:是否显示合并的群集。
    9. color_threshold:显示不同颜色的阈值,用于将不同群集算法聚类为不同颜色。
    10. above_threshold_color:超过阈值的线段颜色。
    11. orientation:图形的方向,可以选择 'top''bottom''left''right'

    hierarchy.linkage参数:

    1. y:输入的数据集,可以是一个离散的样本点的集合,或者是一个已经计算好的距离矩阵。
    2. method:指定层次聚类的算法,常用的方法包括 “single”(最近邻),“complete”(最远邻),“average”(平均距离),“weighted”(加权平均法),默认为 “single”。
    3. metric:指定用于计算距离的方法,常见的包括 “euclidean”(欧氏距离),“manhattan”(曼哈顿距离),“cosine”(余弦相似度)等,默认为 “euclidean”。
    4. optimal_ordering:是否对连接矩阵进行优化,以获得更好的划分,默认为 False
    5. pooling_func:当 y 是浮点型矩阵时,指定汇聚的方法,默认为 np.mean,即使用平均值。

    假设我们输出Z值,获得以下结果:

    1. from scipy.cluster import hierarchy # 导入层次聚类算法
    2. import numpy as np
    3. import pandas as pd
    4. # 生成示例数据
    5. np.random.seed(0)
    6. data = np.random.random((8,1))
    7. # 使用树状图找到最佳聚类数
    8. Z = hierarchy.linkage(data,method='weighted',metric='euclidean')
    9. row_dist_linkage = pd.DataFrame(Z,
    10. columns=['Row Label 1','Row Label 2','Distance','Item Number in Cluster'],
    11. index=['Cluster %d' % (i+1) for i in range(Z.shape[0])])
    12. print("\nData Distance via Linkage: \n",row_dist_linkage)

    其中,第一列和第二列代表节点标签,包含叶子和枝子;第三列代表叶叶(或叶枝,枝枝)之间的距离;第四列代表该层次类中含有的样本数(记录数)。注:因此,我们可以第三列距离结合图来确定不同簇的样本数量。这里的数量为(n-1),即样本总数减1。

    另外一种方法(注意:sklearn必须是最新版,我的是0.24.2---之前我的是0.19的,否则报错):

    sklearn更新升级:

    pip install -U scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple
    1. import numpy as np
    2. from scipy.cluster.hierarchy import dendrogram
    3. from sklearn.cluster import AgglomerativeClustering
    4. import matplotlib.pyplot as plt
    5. X = np.random.random((10,1))
    6. def plot_dendrogram(model, **kwargs):
    7. # 创建链接矩阵,然后绘制树状图
    8. # 创建每个节点的样本计数
    9. counts = np.zeros(model.children_.shape[0])
    10. n_samples = len(model.labels_)
    11. for i, merge in enumerate(model.children_):
    12. current_count = 0
    13. for child_idx in merge:
    14. if child_idx < n_samples:
    15. current_count += 1 # 叶子节点
    16. else:
    17. current_count += counts[child_idx-n_samples]
    18. counts[i] = current_count
    19. linkage_matrix = np.column_stack([model.children_, model.distances_,
    20. counts]).astype(float)
    21. print(linkage_matrix)
    22. # 绘制相应的树状图
    23. dendrogram(linkage_matrix, **kwargs)
    24. # 设置 distance_threshold = 0 ,以确保我们计算的是完整的树
    25. model = AgglomerativeClustering(distance_threshold=0, n_clusters=None)
    26. model = model.fit(X)
    27. plt.title('Hierarchical Clustering Dendrogram')
    28. # 绘制树状图的前三个级别
    29. plot_dendrogram(model, truncate_mode='level', p=3)
    30. plt.xlabel("Number of points in node (or index of point if no parenthesis).")
    31. plt.show()

    2、R语言

    数据:iris.zip

    1. setwd("D:/Desktop/0000/R") #更改路径
    2. df <- read.csv("iris.csv",header = T, row.names = 1) #读取工作路径文件
    3. head(df) #查看前6行
    4. hc <- hclust(dist(df))
    5. library(ggtree)
    6. ggtree(hc,layout="circular",branch.length = "daylight")+
    7. xlim(NA,3)+
    8. geom_tiplab2(offset=0.1,
    9. size=2)+
    10. #geom_text(aes(label=node))+
    11. geom_highlight(node = 152,fill="red")+
    12. geom_highlight(node=154,fill="steelblue")+
    13. geom_highlight(node=155,fill="green")+
    14. geom_cladelabel(node=152,label="virginica",
    15. offset=1.2,barsize = 2,
    16. vjust=-0.5,color="red")+
    17. geom_cladelabel(node=154,label="versicolor",
    18. offset=1.2,barsize = 2,
    19. hjust=1.2,color="steelblue")+
    20. geom_cladelabel(node=155,label="setosa",
    21. offset=1.2,barsize = 2,
    22. hjust=-1,color="green")

    如果没有安装ggtree则先安装

    1. install.packages("BiocManager")
    2. BiocManager::install('ggtree')
    3. 当然,我们可以指定版本安装:BiocManager::install('ggtree',version = "3.17")

    对上面代码在修改下:

    1. setwd("D:/Desktop/0000/R") #更改路径
    2. df <- read.csv("iris.csv",header = T, row.names = 1) #读取工作路径文件
    3. head(df) #查看前6行
    4. hc <- hclust(dist(df))
    5. library(ggtree)
    6. help(package="ggtree")
    7. ggtree(hc,layout="circular",branch.length=5,size = 0.5)+ #size = 0.5 线宽
    8. xlim(NA,3)+
    9. #theme_tree2()+ #显示x坐标范围
    10. geom_tiplab2(size=3,align=T,linesize = -0.0,linetype = 0,offset = 0.0001)+ #size = 3 标签大小
    11. #align=T 标签右对齐 linesize = 16 标签右对齐后会有线连接,
    12. #设置线的粗细 linetype = 1 设置线的类型,默认是虚线 offset=2设置标签距离枝末端的距离
    13. #geom_text(aes(label=node))+
    14. geom_highlight(node = 152,fill="red",
    15. #extendto = 0.05, #延长
    16. #extend =-0, #反向延长
    17. #alpha = 0.2
    18. )+
    19. geom_highlight(node=154,fill="steelblue")+
    20. geom_highlight(node=155,fill="green")+
    21. geom_cladelabel(node=152,label="virginica",
    22. offset=1.5,barsize = 2,
    23. vjust=-0.8,hjust=0.5,color="red")+
    24. geom_cladelabel(node=154,label="versicolor",
    25. offset=1.5,barsize = 2,
    26. hjust=1.2,color="steelblue")+
    27. geom_cladelabel(node=155,label="setosa",
    28. offset=1.5,barsize = 2,
    29. hjust=-1,vjust=-1,color="green")#+
    30. # #另外一种分类条带的方法
    31. # geom_strip(51,#起点,设置的是外节点
    32. # 114,#终点
    33. # label= "cluster 2", #分类标签名
    34. # offset= 1.5, #条带的偏移量
    35. # offset.text = 3, #标签的偏移量
    36. # barsize= 2, #条带宽度
    37. # #extend= 0.2, #延长条带的长度(两端)
    38. # color= "#9467BDFF", #条带颜色
    39. # angle= 90,#标签旋转角度
    40. # hjust= "center"
    41. # )

    又或者:

    1. setwd("D:/Desktop/0000/R") #更改路径
    2. df <- read.csv("iris.csv",header = T, row.names = 1) #读取工作路径文件
    3. head(df) #查看前6行
    4. hc <- hclust(dist(df))
    5. library(ggtree)
    6. help(package="ggtree")
    7. ggtree(hc,layout="circular",branch.length=5,size = 0.5)+ #size = 0.5 线宽
    8. xlim(NA,3)+
    9. #theme_tree2()+ #显示x坐标范围
    10. geom_tiplab2(size=2,align=T,linesize = -0.0,linetype = 0,offset = 0.2)+ #size = 3 标签大小
    11. #align=T 标签右对齐 linesize = 16 标签右对齐后会有线连接,
    12. #设置线的粗细 linetype = 1 设置线的类型,默认是虚线 offset=2设置标签距离枝末端的距离
    13. #geom_text(aes(label=node))+
    14. geom_cladelab(node=152,label="",
    15. barcolor="red",
    16. barsize = 5,
    17. extend=0.5,
    18. offset=0.6,
    19. alpha = 0.5)+
    20. geom_cladelab(node=154,label="",
    21. barcolor="steelblue",
    22. barsize = 5,
    23. extend=0.5,
    24. offset=0.7,
    25. alpha = 0.5)+
    26. geom_cladelab(node=155,label="",
    27. barcolor="green",
    28. barsize = 5,
    29. extend=0.5,
    30. offset=0.6,
    31. alpha = 0.5)

    除了上面这种方式外,我们还可以使用下面的方式获取(节点对齐):

    1. setwd("D:/Desktop/0000/R") #更改路径
    2. library(dendextend) #install.packages("dendextend")
    3. library(circlize) #install.packages("circlize")
    4. df <- read.csv("iris.csv",header = T, row.names = 1) #读取工作路径文件
    5. head(df) #查看前6行
    6. aa <- hclust(dist(df))
    7. # 设置画布大小为4英寸宽,4英寸高
    8. par(mar = c(4, 4, 2, 2) + 0.1)
    9. png("output.png", width = 4, height = 4, units = "in", res = 600)
    10. hc <- as.dendrogram(aa) %>%
    11. set("branches_lwd", c(1.5)) %>% # 线条粗细
    12. set("labels_cex", c(.9)) # 字体大小
    13. # 颜色
    14. hc <- hc %>%
    15. color_branches(k = 10) %>% #树状分支线条颜色
    16. color_labels(k = 10) #文字标签颜色
    17. # Fan tree plot with colored labels
    18. circlize_dendrogram(hc,
    19. labels_track_height = NA,
    20. dend_track_height = 0.7)
    21. # 结束绘图并关闭设备
    22. dev.off()

    文件数据样式:

    更多学习视频:【R包使用】ggtree美化树状图_哔哩哔哩_bilibili树状图展示聚类分析的结果_哔哩哔哩_bilibili

    3、密度聚类(DBSCAN)

    简单例子:

    下面是KMeans、层次聚类的结果:

    那么使用密度聚类结果为:

    代码:

    1. from sklearn.cluster import KMeans
    2. import matplotlib.pyplot as plt
    3. from sklearn.cluster import AgglomerativeClustering
    4. from sklearn.cluster import DBSCAN
    5. import numpy as np
    6. # 创建虚拟数据
    7. x1 = np.random.random((100,1))*10
    8. x2 = np.random.random((100,1))*1
    9. X = np.concatenate((x1,x2),axis=0)
    10. f,(ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(8, 3))
    11. # KMeans
    12. km = KMeans(n_clusters=2).fit(X) # n_clusters=None, n_init=1, random_state=0
    13. y_km = km.labels_
    14. for i in range(max(y_km+1)):
    15. ax1.scatter(np.array([i for i in range(len(X))])[y_km==i],X[y_km==i], marker='o', s=40, label='Cluster '+str(i))
    16. ax1.set_title('K-means')
    17. ax1.set_xlabel('Feature 1')
    18. ax1.set_ylabel('Feature 2')
    19. # 层次聚类
    20. ac = AgglomerativeClustering().fit(X)
    21. y_ac = ac.labels_
    22. for i in range(max(y_ac+1)):
    23. ax2.scatter(np.array([i for i in range(len(X))])[y_ac==i],X[y_ac==i], marker='o', s=40, label='Cluster '+str(i))
    24. ax2.set_title('Agglomerative')
    25. ax2.set_xlabel('Feature 1')
    26. ax2.set_ylabel('Feature 2')
    27. # 密度聚类
    28. # eps 就是半径,min_samples就是 MinPts 值
    29. db = DBSCAN(min_samples=10).fit(X) # eps=0.2, min_samples=3, metric='euclidean'
    30. y_db = db.labels_
    31. for i in range(max(y_db+1)):
    32. ax3.scatter(np.array([i for i in range(len(X))])[y_db==i],X[y_db==i], marker='o', s=40, label='Cluster '+str(i))
    33. ax3.set_title('DBSCAN')
    34. ax3.set_xlabel('Feature 1')
    35. ax3.set_ylabel('Feature 2')
    36. # 原始数据
    37. ax4.scatter(np.array([i for i in range(len(X))])[:100], X[:100],c='lightblue',edgecolor='black', marker='o', s=40, label='Cluster 1')
    38. ax4.scatter(np.array([i for i in range(len(X))])[100:], X[100:], c='red',edgecolor='black', marker='s', s=40, label='Cluster 2')
    39. ax4.set_title('Original data')
    40. ax4.set_xlabel('Feature 1')
    41. ax4.set_ylabel('Feature 2')
    42. plt.legend()
    43. plt.tight_layout()
    44. plt.show()

    我通过创建三个不同的聚类中心数据:

    1. from sklearn.cluster import KMeans
    2. import matplotlib.pyplot as plt
    3. from sklearn.cluster import AgglomerativeClustering
    4. from sklearn.cluster import DBSCAN
    5. from sklearn.datasets import make_blobs
    6. import numpy as np
    7. # 创建虚拟数据
    8. centers = [[5], [0],[-5]]
    9. X, labels_true = make_blobs(n_samples=200, centers=centers,
    10. cluster_std=0.4, random_state=0)
    11. f,(ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(8, 3))
    12. # KMeans
    13. km = KMeans(n_clusters=2).fit(X) # n_clusters=None, n_init=1, random_state=0
    14. y_km = km.labels_
    15. for i in range(max(y_km+1)):
    16. ax1.scatter(np.array([i for i in range(len(X))])[y_km==i],X[y_km==i], marker='o', s=40, label='Cluster '+str(i))
    17. ax1.set_title('K-means')
    18. ax1.set_xlabel('Feature 1')
    19. ax1.set_ylabel('Feature 2')
    20. # 层次聚类
    21. ac = AgglomerativeClustering().fit(X)
    22. y_ac = ac.labels_
    23. for i in range(max(y_ac+1)):
    24. ax2.scatter(np.array([i for i in range(len(X))])[y_ac==i],X[y_ac==i], marker='o', s=40, label='Cluster '+str(i))
    25. ax2.set_title('Agglomerative')
    26. ax2.set_xlabel('Feature 1')
    27. ax2.set_ylabel('Feature 2')
    28. # 密度聚类
    29. # eps 就是半径,min_samples就是 MinPts 值
    30. db = DBSCAN(min_samples=10).fit(X) # eps=0.2, min_samples=3, metric='euclidean'
    31. y_db = db.labels_
    32. for i in range(max(y_db+1)):
    33. ax3.scatter(np.array([i for i in range(len(X))])[y_db==i],X[y_db==i], marker='o', s=40, label='Cluster '+str(i))
    34. ax3.set_title('DBSCAN')
    35. ax3.set_xlabel('Feature 1')
    36. ax3.set_ylabel('Feature 2')
    37. # 原始数据
    38. ax4.scatter(np.array([i for i in range(len(X))]), X, marker='o', s=40)
    39. ax4.set_title('Original data')
    40. ax4.set_xlabel('Feature 1')
    41. ax4.set_ylabel('Feature 2')
    42. plt.tight_layout()
    43. plt.show()

    因此,遇到此类数据,密度聚类效果更好。

  • 相关阅读:
    【Ajax】全面详细了解git的基础操作【万字教学+面试常客】
    SCA算法优化脉冲耦合神经网络的图像自动分割(Matlab代码实现)
    揭秘!付费会员制下的那些小心机!
    SpringBoot使用AOP详解
    Centos 7.9 一键安装 Oracle 12CR2(240116)单机 PDB
    航天联志Aisino-AISINO26081R服务器通过调BIOS用U盘重新做系统(windows系统通用)
    华为OD机试 - 敏感字段加密(Java 2023 B卷 100分)
    ChatGPT 在做什么,为什么有效?
    搭载紫光展锐V510平台 移远通信RG500U-EA 5G模组获全球首个GCF认证
    毕业设计之基于node.js+Vue的企业员工信息管理系统 Elementui
  • 原文地址:https://blog.csdn.net/qq_45100200/article/details/132919002