机器学习算法(21)python实现用SciPy进行全连接的凝聚层次聚类算法
现研究另一种基于原型的聚类算法-全连接的凝聚层次聚类算法。其中三个概念分别代表:
层次聚类:它允许绘制树状图(二进制层次聚类的可视化);不需要预先指定集群数目。
凝聚聚类:首先从每个集群包括单个样本开始,合并最接近的集群,直到只剩下一个集群为止。
全连接方法:计算两个集群中最不相似的成员之间的距离,然后合并两个集群即比较最不相似的成员然后合并。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.spatial.distance import pdist, squareform
from scipy.cluster.hierarchy import linkage
from scipy.cluster.hierarchy import dendrogram
# 随机生成样本
np.random.seed(123)
variables = ['X', 'Y', 'Z']
labels = ['ID_0', 'ID_1', 'ID_2', 'ID_3', 'ID_4']
X = np.random.random_sample([5, 3])*10
df = pd.DataFrame(X, columns=variables, index=labels)
print(df)
# 用SciPy的spatial.distance子模块的pdist函数计算距离矩阵作为层次聚类算法的输入
row_dist = pd.DataFrame(squareform(pdist(df, metric='euclidean')), # 欧氏距离
columns=labels,
index=labels)
print(row_dist)
# 调用SciPy中的cluster.hiera-rchy子模块的linkage函数来应用全连接凝聚方法处理集群,
# 处理结果将返回在所谓的连接矩阵中。
# print(help(linkage)) # 查看方法
row_clusters = linkage(pdist(df, metric='euclidean'),
method='complete', metric='euclidean') # 全连接+欧氏距离,返回值:连接矩阵
'''
连接矩阵:
连接矩阵由若干行组成,其中每行代表一个合并。
第一列和第二列代表每个集群中相似度最低的成员,第三列报告这些成员之间的距离。
最后一列返回每个集群成员的个数
'''
print(pd.DataFrame(row_clusters,
columns=['row label 1', 'row label 2',
'distance', 'no. of items in clust.'],
index=['cluster %d' % (i + 1)
for i in range(row_clusters.shape[0])]))
# 层次聚类树状图
row_dendr = dendrogram(row_clusters,
labels=labels,
# make dendrogram black (part 2/2)
# color_threshold=np.inf
)
plt.tight_layout()
plt.ylabel('Euclidean distance')
#plt.savefig('images/11_11.png', dpi=300,
# bbox_inches='tight')
# plt.show()
# 把树状图附加到热度图
fig = plt.figure(figsize=(8, 8), facecolor='white') # facecolor:背景颜色
# add_axes为新增子区域,该区域可以座落在figure内任意位置,且该区域可任意设置大小
# 可以用来做一些子图,图中图
axd = fig.add_axes([0.09, 0.1, 0.2, 0.6])
row_dendr2 = dendrogram(row_clusters, orientation='left') # orientation:指定方向
df_rowclust = df.iloc[row_dendr2['leaves'][::-1]]
# 根据排序后的DataFrame构建热度图
# 热度图中行的顺序反映了树状图中样本的聚类情况
# 热度图中每个样本的颜色编码和特征为数据集做很好的概括
axm = fig.add_axes([0.23, 0.1, 0.6, 0.6]) # x-pos, y-pos, width, height
'''interpolation:使用的插值方法
cmap:hot_r,其中_r的意思是就是按照颜色越深,数值越大,
如果想数值越大,颜色越浅,只需要去掉_r,直接为hot就行。
同时这个hot是热图配色的其中一个主题,主题色参数可选:
hot 从黑平滑过度到红、橙色和黄色的背景色,然后到白色。
cool 包含青绿色和品红色的阴影色。从青绿色平滑变化到品红色。
gray 返回线性灰度色图。
bone 具有较高的蓝色成分的灰度色图。该色图用于对灰度图添加电子的视图。
white 全白的单色色图。
spring 包含品红和黄的阴影颜色。
summer 包含绿和黄的阴影颜色。
autumn 从红色平滑变化到橙色,然后到黄色。
winter 包含蓝和绿的阴影色。
'''
cax = axm.matshow(df_rowclust, interpolation='nearest', cmap='hot_r')
# 去除坐标轴的间隔标记和隐藏坐标轴的轴线来美化修树状图
axd.set_xticks([])
axd.set_yticks([])
# 隐藏树状图边框
for i in axd.spines.values():
i.set_visible(False)
# 添加颜色条
fig.colorbar(cax)
axm.set_xticklabels([''] + list(df_rowclust.columns))
axm.set_yticklabels([''] + list(df_rowclust.index))
#plt.savefig('images/11_12.png', dpi=300)
plt.show()
print(axd.spines.values())
运行结果:
X Y Z
ID_0 6.964692 2.861393 2.268515
ID_1 5.513148 7.194690 4.231065
ID_2 9.807642 6.848297 4.809319
ID_3 3.921175 3.431780 7.290497
ID_4 4.385722 0.596779 3.980443
ID_0 ID_1 ID_2 ID_3 ID_4
ID_0 0.000000 4.973534 5.516653 5.899885 3.835396
ID_1 4.973534 0.000000 4.347073 5.104311 6.698233
ID_2 5.516653 4.347073 0.000000 7.244262 8.316594
ID_3 5.899885 5.104311 7.244262 0.000000 4.382864
ID_4 3.835396 6.698233 8.316594 4.382864 0.000000
row label 1 row label 2 distance no. of items in clust.
cluster 1 0.0 4.0 3.835396 2.0
cluster 2 1.0 2.0 4.347073 2.0
cluster 3 3.0 5.0 5.899885 3.0
cluster 4 6.0 7.0 8.316594 5.0
odict_values([<matplotlib.spines.Spine object at 0x00000138B5584DF0>, <matplotlib.spines.Spine object at 0x00000138B5584EE0>, <matplotlib.spines.Spine object at 0x00000138B5584FD0>, <matplotlib.spines.Spine object at 0x00000138B559B100>])
运行结果图: