你:小敏,你记得我跟你提过那部超好看的家庭伦理剧《任家风云》吗?我简直追得不亦乐乎!
小敏:哦,是那个有任家豪和任家明的剧吧?我有点印象,但没看过,讲讲看?
你:好的,但得先给你介绍一下主要人物。你知道,这剧情比较复杂。首先,任家豪和任家明是一对长得几乎一模一样的双胞胎。最有趣的是,任家明的女朋友陈芳,一个聪明又善良的女孩...
小敏:等等,你说的是任家明的女朋友,对吧?
你:没错,但后来,陈芳竟然成了任家豪的妻子!这其中的误会和错综复杂的情感简直是戏剧性的爆棚!
小敏:哎呀,慢一点,我已经迷糊了。陈芳是谁的妻子来着?
你:哦,我激动地有点快了。让我再捋一捋。陈芳本来是任家明的女朋友,结果因为舒丹的一些小手段,不知怎么的,陈芳最后和任家豪走到了一起。
小敏:舒丹?她又是谁?
你:好问题!舒丹是个关键人物,她聪明而又心思细腻,是任家明的初恋,但后来变成了他们家族关系中的一个“导火索”。哦,对了,我忘了说,任家豪和任家明的父亲是任建国,一个非常尊重传统的人,而他们的母亲是方婷,家里的调解者。
小敏:哇塞,这么多人,感觉好复杂啊。
你:确实有点,这就是这部剧的魅力所在!等等,我来画个简单的家族谱系图给你看,这样就一目了然了。
(我画了一个家族谱系图)
你:看,任家豪和任家明是双胞胎兄弟,陈芳是任家明的前女友,现在是任家豪的老婆。舒丹是任家明的初恋,而任建国和方婷分别是这对双胞胎的父母。
小敏:哦,现在清楚多了!有图有真相,终于弄明白谁和谁是一家人了。那你继续讲故事吧,我想知道这个家族后来怎么样了!
你:好的,那我接着说。事情的起点是陈芳和任家明的一段感情,但是...
让我们用《任家风云》的角色关系来打比方,介绍聚集式层次聚类算法。
在你给小敏介绍情节和人物时,你手头有一堆《任家风云》剧中角色的卡片,每张卡片上写着一个角色的名字,比如“任家豪”、“任家明”、“陈芳”等等。你的任务是根据这些角色之间的关系,把它们按照家族成员归类。
通过这样的方式,聚集式层次聚类算法帮助我们理解和梳理数据点之间的关系,就像我们通过角色之间的关系来组织《任家风云》的剧情一样。最终,我们能够看到一个清晰的层次结构,了解每个角色在大家族中的位置。
聚集式层次聚类算法(Agglomerative Hierarchical Clustering)是一种常见的层次聚类方法,它的基本思想是将数据集中的每个样本看作一个初始聚类簇,然后在算法运行的每一步中找出距离最近的两个聚类簇进行合并,这个过程不断重复,直到达到预定的聚类簇数量或者满足某个终止条件。
初始化: 开始时,假设有 个样本,则将每个样本看作一个单独的聚类簇,这样就有了 个聚类簇。
计算距离: 计算所有聚类簇之间的距离。距离的计算可以有多种方式,如单链接(最近邻),全链接(最远邻),平均链接(组间平均)等。例如,使用最近邻的距离计算公式可以表示为:
其中 是聚类簇 和聚类簇 之间的最小距离, 是样本 和样本 之间的距离。
合并聚类簇: 找出所有聚类簇对中距离最近的一对,将它们合并成一个新的聚类簇。
更新距离: 合并后,需要重新计算新形成的聚类簇与其他所有聚类簇之间的距离。
重复步骤3和4: 不断重复合并聚类簇和更新距离的步骤,直到所有样本都合并到一个聚类簇中,或者达到其他停止条件(例如聚类簇数量达到用户指定的值)。
生成树状图: 在聚类过程中,每一次合并都可以在树状图(Dendrogram)上进行记录,从而可以观察到聚类的层次结构。
假设有A,B,C,D四个样本,初始时它们各自是一个聚类簇:。
假设通过计算发现A和B之间的距离最近,那么合并它们:。
接着重新计算距离,假设这次C和D距离最近,合并它们:。
最后合并所有聚类簇,得到最终的聚类簇: 。
在这个过程中,可以绘制出一棵树状图来表示聚类的过程和层次结构。
聚集式层次聚类算法的优点是不需要预先指定聚类的数量,且可以通过树状图直观地看出数据的层次结构。缺点是计算量较大,尤其是在样本数量很多的时候,每次合并都需要重新计算距离,因此算法的时间复杂度较高。
1import numpy as np
2from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
3from sklearn.metrics import silhouette_score
4from matplotlib import pyplot as plt
5from sklearn.datasets import make_blobs
6
7# 创建模拟数据
8X, true_labels = make_blobs(n_samples=20, centers=3, cluster_std=0.60, random_state=0)
9
10# 使用层次聚类进行链接
11linked = linkage(X, 'ward')
12
13# 根据树状图选择一个合理的距离阈值来划分聚类
14distance_threshold = 3
15clusters = fcluster(linked, distance_threshold, criterion='distance')
16
17# 计算轮廓系数
18silhouette_avg = silhouette_score(X, clusters)
19print(f'The average silhouette_score is : {silhouette_avg}')
20
21# 绘制树状图
22plt.figure(figsize=(10, 7))
23dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
24plt.title(f'Hierarchical Clustering Dendrogram (threshold={distance_threshold})')
25plt.xlabel('Index of point')
26plt.ylabel('Distance')
27plt.axhline(y=distance_threshold, color='r', linestyle='--') # 画出我们选择的阈值线
28plt.show()
1import numpy as np
2from scipy.cluster.hierarchy import dendrogram, linkage, fcluster
3from sklearn.metrics import silhouette_score
4from matplotlib import pyplot as plt
5from sklearn.datasets import make_blobs
6
7# 创建模拟数据
8X, true_labels = make_blobs(n_samples=20, centers=3, cluster_std=0.60, random_state=0)
9
10# 使用层次聚类进行链接
11linked = linkage(X, 'ward')
12
13# 根据树状图选择一个合理的距离阈值来划分聚类
14distance_threshold = 3
15clusters = fcluster(linked, distance_threshold, criterion='distance')
16
17# 计算轮廓系数
18silhouette_avg = silhouette_score(X, clusters)
19print(f'The average silhouette_score is : {silhouette_avg}')
20
21# 绘制树状图
22plt.figure(figsize=(10, 7))
23dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
24plt.title(f'Hierarchical Clustering Dendrogram (threshold={distance_threshold})')
25plt.xlabel('Index of point')
26plt.ylabel('Distance')
27plt.axhline(y=distance_threshold, color='r', linestyle='--') # 画出我们选择的阈值线
28plt.show()
在这段代码中:
silhouette_score
函数来计算轮廓系数。这个函数需要原始数据点和对应的聚类标签。请注意,轮廓系数需要真实的聚类标签来进行计算。在实际应用中,如果没有真实的聚类标签(这是聚类的通常情况),我们只能基于数据点和它们所属的聚类来评估聚类效果。轮廓系数在这种情况下仍然是一个有用的度量。