-
2022-04-03 17:46:50
聚类算法及python实现——层次聚类
构建二叉树
步骤
step1:将每个样品都看作一类
step2:计算每个样品两两之间的距离
step3:合并距离最近的两类变成一个新的类
step4:计算各个类之间的距离,合并,直至只有一类
类与类的距离计算method:
(1)最短距离法single
(2)最长距离法complete
(3)中间距离法weighted
(4)重心法centroid
(5)类平均法average
(6)离差平方和法wardpython代码
from scipy.cluster import hierarchy from scipy.cluster.hierarchy import linkage hc = linkage(data, method='single', metric='euclidean')
优势
(1)发现类别间的层次关系
(2)适用于任何形状的聚类
(3)可以不预先设置类别数缺陷
(1)已执行的类不能撤销,类之间也不能交换对象
(2)计算复杂度高,大数据集不适用
(3)可能聚类成链状更多相关内容 -
Python实现简单层次聚类算法以及可视化
2020-09-19 12:55:34主要为大家详细介绍了Python实现简单层次聚类算法以及可视化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
Python聚类算法之凝聚层次聚类实例分析
2020-09-21 19:13:18主要介绍了Python聚类算法之凝聚层次聚类的原理与具体使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下 -
python实现聚类算法原理
2020-12-24 08:23:52K均值聚类算法的python实现,以及聚类算法与EM最大算法的关系 参考引用 先上一张gif的k均值聚类算法动态图片,让大家对算法有个感性认识: 其中:N=200代表有200个样本,不同的颜色代表不同的簇(其中 3种颜色为3... -
Python实现Kmeans聚类算法
2020-12-23 13:08:06本节内容:本节内容是根据上学期所上的模式识别课程的作业整理而来,第一道题目是Kmeans聚类算法,数据集是Iris(鸢尾花的数据集),分类数k是3,数据维数是4。 关于聚类 聚类算法是这样的一种算法:给定样本数据... -
聚类算法之层次聚类(Python实现)
2021-02-05 13:38:57层次聚类算法介绍假设有 n 个待聚类的样本,对于层次聚类算法,它的步骤是:步骤一:(初始化)将每个样本都视为一个聚类;步骤二:计算各个聚类之间的相似度;步骤三:寻找最近的两个聚类,将他们归为一类;步骤四:...起步
层次聚类( Hierarchical Clustering )是聚类算法的一种,通过计算不同类别的相似度类创建一个有层次的嵌套的树。
层次聚类算法介绍
假设有 n 个待聚类的样本,对于层次聚类算法,它的步骤是:
步骤一:(初始化)将每个样本都视为一个聚类;
步骤二:计算各个聚类之间的相似度;
步骤三:寻找最近的两个聚类,将他们归为一类;
步骤四:重复步骤二,步骤三;直到所有样本归为一类。
整个过程就是建立一棵树,在建立的过程中,可以在步骤四设置所需分类的类别个数,作为迭代的终止条件,毕竟都归为一类并不实际。
聚类之间的相似度
聚类和聚类之间的相似度有什么来衡量呢?既然是空间中的点,可以采用距离的方式来衡量,一般有下面三种:
Single Linkage
又叫做 nearest-neighbor ,就是取两个类中距离最近的两个样本的距离作为这两个集合的距离。这种计算方式容易造成一种叫做 Chaining 的效果,两个 cluster 明明从“大局”上离得比较远,但是由于其中个别的点距离比较近就被合并了,并且这样合并之后 Chaining 效应会进一步扩大,最后会得到比较松散的 cluster 。
Complete Linkage
这个则完全是 Single Linkage 的反面极端,取两个集合中距离最远的两个点的距离作为两个集合的距离。其效果也是刚好相反的,限制非常大。这两种相似度的定义方法的共同问题就是指考虑了某个有特点的数据,而没有考虑类内数据的整体特点。
Average Linkage 这种方法就是把两个集合中的点两两的距离全部放在一起求均值,相对也能得到合适一点的结果。有时异常点的存在会影响均值,平常人和富豪平均一下收入会被拉高是吧,因此这种计算方法的一个变种就是取两两距离的中位数。
python 实现层次聚类
空间中点的距离使用欧式距离:
import math
import numpy as np
def euler_distance(point1: np.ndarray, point2: list) -> float:
"""
计算两点之间的欧拉距离,支持多维
"""
distance = 0.0
for a, b in zip(point1, point2):
distance += math.pow(a - b, 2)
return math.sqrt(distance)
定义聚类数的节点:
class ClusterNode(object):
def __init__(self, vec, left=None, right=None, distance=-1, id=None, count=1):
"""
:param vec: 保存两个数据聚类后形成新的中心
:param left: 左节点
:param right: 右节点
:param distance: 两个节点的距离
:param id: 用来标记哪些节点是计算过的
:param count: 这个节点的叶子节点个数
"""
self.vec = vec
self.left = left
self.right = right
self.distance = distance
self.id = id
self.count = count
vec 表示合并后的聚类中心,是一个点,代表整个聚类的位置;distance 表示左节点和右节点的距离。
计算层次聚类算法的类:
class Hierarchical(object):
def __init__(self, k = 1):
assert k > 0
self.k = k
self.labels = None
def fit(self, x):
nodes = [ClusterNode(vec=v, id=i) for i,v in enumerate(x)]
distances = {}
point_num, future_num = np.shape(x) # 特征的维度
self.labels = [ -1 ] * point_num
currentclustid = -1
while len(nodes) > self.k:
min_dist = math.inf
nodes_len = len(nodes)
closest_part = None # 表示最相似的两个聚类
for i in range(nodes_len - 1):
for j in range(i + 1, nodes_len):
# 为了不重复计算距离,保存在字典内
d_key = (nodes[i].id, nodes[j].id)
if d_key not in distances:
distances[d_key] = euler_distance(nodes[i].vec, nodes[j].vec)
d = distances[d_key]
if d < min_dist:
min_dist = d
closest_part = (i, j)
# 合并两个聚类
part1, part2 = closest_part
node1, node2 = nodes[part1], nodes[part2]
new_vec = [ (node1.vec[i] * node1.count + node2.vec[i] * node2.count ) / (node1.count + node2.count)
for i in range(future_num)]
new_node = ClusterNode(vec=new_vec,
left=node1,
right=node2,
distance=min_dist,
id=currentclustid,
count=node1.count + node2.count)
currentclustid -= 1
del nodes[part2], nodes[part1] # 一定要先del索引较大的
nodes.append(new_node)
self.nodes = nodes
self.calc_label()
def calc_label(self):
"""
调取聚类的结果
"""
for i, node in enumerate(self.nodes):
# 将节点的所有叶子节点都分类
self.leaf_traversal(node, i)
def leaf_traversal(self, node: ClusterNode, label):
"""
递归遍历叶子节点
"""
if node.left == None and node.right == None:
self.labels[node.id] = label
if node.left:
self.leaf_traversal(node.left, label)
if node.right:
self.leaf_traversal(node.right, label)
最后将聚类的列表标记保存于 labels 中。
测试
与 sklearn 进行对比:
iris = datasets.load_iris()
my = Hierarchical(4)
my.fit(iris.data)
print(np.array(my.labels))
sk = cluster.AgglomerativeClustering(4)
sk.fit(iris.data)
print(sk.labels_)
得到输出:
[3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 2 1 2 2 2 2 1 2 2 2 2
2 2 1 1 2 2 2 2 1 2 1 2 1 2 2 1 1 2 2 2 2 2 1 2 2 2 2 1 2 2 2 1 2 2 2 1 2
2 1]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 3 2 3 2 3 2 3 3 2 3 2 3 2 3 3 2 3 2 2 2 2
2 2 2 0 2 3 3 3 3 2 3 2 2 2 3 3 3 2 3 3 3 3 3 2 3 3 0 2 0 0 0 0 3 0 0 0 0
0 0 2 2 0 0 0 0 2 0 2 0 2 0 0 2 2 0 0 0 0 0 2 2 0 0 0 2 0 0 0 2 0 0 0 2 0
0 2]
结果还算是理想的。
层次聚类的优缺点
优点:
一次性得到聚类树,后期再分类无需重新计算;
相似度规则容易定义;
可以发现类别的层次关系。
缺点:
计算复杂度高,不适合数据量大的;
算法很可能形成链状。
附录
-
层次聚类(AGNES)算法(Python)
2019-05-31 14:15:10层次聚类(AGNES)算法(Python) 是聚类算法的一种,通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。...AGNES是常用的一种层次聚类算法 使用场景:用于簇的数量较多,有连接约束等情况 -
K-means聚类算法介绍与利用python实现的代码示例
2020-12-24 13:22:34今天说K-means聚类算法,但是必须要先理解聚类和分类的区别,很多业务人员在日常分析时候不是很严谨,混为一谈,其实二者有本质的区别。 分类其实是从特定的数据中挖掘模式,作出判断的过程。比如Gmail邮箱里有垃圾... -
关于层次聚类算法的python实现
2021-03-17 02:50:48from scipy.cluster import hierarchy0.层次聚类的概念层次聚类和k-means一样都是很常用的聚类方法。...层次聚类又分为自底而上的聚合层次聚类和自顶而下的分裂层次聚类。0.1 聚合层次聚类每一个点初始为1类,得到N(...from scipy.cluster import hierarchy
0.层次聚类的概念
层次聚类和k-means一样都是很常用的聚类方法。层次聚类是对群体的划分,最终将样本划分为树状的结构。他的基本思路是每个样本先自成一类,然后按照某种规则进行合并,直到只有一类或者某一类的样本只有一个点。层次聚类又分为自底而上的聚合层次聚类和自顶而下的分裂层次聚类。
0.1 聚合层次聚类
每一个点初始为1类,得到N(样本点个数)类,计算每一类之间的距离,计算方法有很多,具体可以参考距离的计算方法。聚合层次聚类方法的终止条件是所有样本点都处于同一类了,或者两类之间的距离超过设置的某个阈值。大多数层次聚类都是聚合层次聚类。
0.2 分裂层次聚类
和聚合层次聚类是反着的,属于自上而下的一种聚类方法。刚开始的时候所有的样本点都位于同一类,然后一步步划分,终止条件是所有的样本点都位于单独的一类,或者两类之间的距离超过设置的某个阈值。
下面这个图可以比较好的说明这个过程:
层次聚类的两种方法
1.凝聚层次聚类算法步骤
1.1 算法过程
1)N个样本单独成类,G1(0)、G2(0)、G3(0)、……、GN(0),0代表初始状态。
2)更新距离矩阵D(n),找出D(n)中最小值,把对应的两类合并为1类。
3)更新距离矩阵D(n+1),重复步骤2-3。
当两类之间的最小距离小于给定的阈值或者所有样本都单独成类的时候,结束算法。
1.2算法案例
有个老师带了五个学生,想给学生分组,让他们分组学习,采用层次聚类来对学生进行聚类,基础数据如下图。
学生基础数据
先来算距离D(0),就采用欧式距离就好了。
初始距离矩阵
找到最小的那两个合并为1类。
合并后的新数据
然后计算更新后的距离D(1)
合并的后新距离
以后的以此类推:
聚类的整体过程
我们看到其实124是一类,35是一类。
画出图来就是下面这个格式:
聚类结果
3.Python处理层次聚类的包
用的是在scipy.cluster里的hierarchy方法,下面来看代码,支持hierarchical clustering 和 agglomerative clustering。
首先来看一些基本函数的用法
linkage
scipy.cluster.hierarchy.linkage(data,method = 'single')
method 参数是类距离的计算公式
singele 两个类之间最短的点的距离
complete 两个类之间最长距离的点的距离
centroid 两个类所有点的中点的距离
pdist计算样本点之间的两两距离
scipy.cluster.hierarchy.distance.pdist(data, metric='euclidean')
metric参数是求距离的方法,默认是欧氏距离,可选的还有:
‘braycurtis’, ‘canberra’, ‘chebyshev’, ‘cityblock’, ‘correlation’, ‘cosine’, ‘dice’, ‘euclidean’, ‘hamming’, ‘jaccard’, ‘jensenshannon’, ‘kulsinski’, ‘mahalanobis’, ‘matching’, ‘minkowski’, ‘rogerstanimoto’, ‘russellrao’, ‘seuclidean’, ‘sokalmichener’, ‘sokalsneath’, ‘sqeuclidean’, ‘yule’
关于求距离的函数我可能还会再更一篇文章,感兴趣的朋友可以等一下。笔者之前算字符相似度自己还写了一个杰尔卡德相似度,现在看看真实太费事了。
dendrogram(linkage)
scipy.cluster.hierarchy.dendrogram(linkage),这个函数是画图用的。
import numpy
import pandas
from sklearn import datasets
import scipy.cluster.hierarchy as hcluster
import scipy
#iris = datasets.load_iris()
#data = iris.data
#target = iris.target
points=scipy.randn(20,4)
# Compute and plot first dendrogram.
linkage = hcluster.linkage(points, method='centroid')
hcluster.dendrogram(linkage, leaf_font_size=10.)
p = hcluster.fcluster( linkage, 3, criterion='maxclust')
聚类结果如下图所示:
聚类结果
以上就是层次聚类的简单应用,当然有不同的需求可以继续探索一些函数的参数,这个方法还是很好用的。
-
层次聚类python实现
2021-10-31 15:30:54层次聚类算法 顾名思义,层次聚类就是一层一层的进行聚类,可以由上向下把大的类别(cluster)分割,叫作分裂法;也可以由下向上对小的类别进行聚合,叫作凝聚法;但是一般用的比较多的是由下向上的凝聚方法。 分裂...层次聚类算法
顾名思义,层次聚类就是一层一层的进行聚类,可以由上向下把大的类别(cluster)分割,叫作分裂法;也可以由下向上对小的类别进行聚合,叫作凝聚法;但是一般用的比较多的是由下向上的凝聚方法。
分裂法:
分裂法指的是初始时将所有的样本归为一个类簇,然后依据某种准则进行逐渐的分裂,直到达到某种条件或者达到设定的分类数目。用算法描述:
输入:样本集合D,聚类数目或者某个条件(一般是样本距离的阈值,这样就可不设置聚类数目)
输出:聚类结果1.将样本集中的所有的样本归为一个类簇; repeat: 2.在同一个类簇(计为c)中计算两两样本之间的距离,找出距离最远的两个样本a,b; 3.将样本a,b分配到不同的类簇c1和c2中; 4.计算原类簇(c)中剩余的其他样本点和a,b的距离,若是dis(a)<dis(b),则将样本点归到c1中,否则归到c2中; util: 达到聚类的数目或者达到设定的条件
凝聚法:
凝聚法指的是初始时将每个样本点当做一个类簇,所以原始类簇的大小等于样本点的个数,然后依据某种准则合并这些初始的类簇,直到达到某种条件或者达到设定的分类数目。用算法描述:
输入:样本集合D,聚类数目或者某个条件(一般是样本距离的阈值,这样就可不设置聚类数目)
输出:聚类结果1.将样本集中的所有的样本点都当做一个独立的类簇; repeat: 2.计算两两类簇之间的距离(后边会做介绍),找到距离最小的两个类簇c1和c2; 3.合并类簇c1和c2为一个类簇; util: 达到聚类的数目或者达到设定的条件
例图:
类簇间距离的计算方法有许多种:
(1)就是取两个类中距离最近的两个样本的距离作为这两个集合的距离,也就是说,最近两个样本之间的距离越小,这两个类之间的相似度就越大
(2)取两个集合中距离最远的两个点的距离作为两个集合的距离
(3)把两个集合中的点两两的距离全部放在一起求一个平均值,相对也能得到合适一点的结果。
e.g.对于u中所有点i和v中所有点j
其中|u|,|v|是聚类u和v中元素的的个数,这也被称为UPGMA算法(非加权组平均)法。
(4)取两两距离的中值,与取均值相比更加能够解除个别偏离样本对结果的干扰。
(5)求每个集合的中心点(就是将集合中的所有元素的对应维度相加然后再除以元素个数得到的一个向量),然后用中心点代替集合再去就集合间的距离实现
接下来以世界银行样本数据集进行简单实现。该数据集以标准格式存储在名为WBClust2013.csv的CSV格式的文件中。其有80行数据和14个变量。数据来源
将数据分为三个聚簇,并且在实现层次聚类之后加入PCA降维与原始结果进行对比。from scipy.cluster.hierarchy import linkage, dendrogram, fcluster import matplotlib.pyplot as plt import pandas as pd import numpy as np data = pd.read_csv('data/WBClust2013.csv') data = data[:20] country = list(data['Country']) data.pop('Country') data_zs = 1.0*data/data.max()#归一化 # print(data_zs) # 以下代码为仅使用层次聚类 plt.figure(figsize=(9, 7)) plt.title("original data") mergings = linkage(data_zs, method='average') dendrogram(mergings, labels=country, leaf_rotation=45, leaf_font_size=8) plt.show() cluster_assignments = fcluster(mergings, t=3.0, criterion='maxclust') print(cluster_assignments) for i in range(1, 4): print('cluster', i, ':') num = 1 for index, value in enumerate(cluster_assignments): if value == i: if num % 5 == 0: print() num += 1 print(country[index], end=' ') print() # 以下代码为加入PCA进行对比 class myPCA(): def __init__(self, X, d=2): self.X = X self.d = d def mean_center(self, data): """ 去中心化 :param data: data sets :return: """ n, m = data.shape for i in range(m): aver = np.sum(self.X[:, i])/n x = np.tile(aver, (1, n)) self.X[:, i] = self.X[:, i]-x def runPCA(self): # 计算协方差矩阵,得到特征值,特征向量 S = np.dot(self.X.T, self.X) S_val, S_victors = np.linalg.eig(S) index = np.argsort(-S_val)[0:self.d] Y = S_victors[:, index] # 得到输出样本集 Y = np.dot(self.X, Y) return Y data_for_pca = np.array(data_zs) pcaObject=myPCA(data_for_pca,d=2) pcaObject.mean_center(data_for_pca) res=pcaObject.runPCA() # plt.figure(figsize=(9, 7)) # plt.title("after pca") # mergings = linkage(res,method='average') # print(mergings) # dendrogram(mergings,labels=country,leaf_rotation=45,leaf_font_size=8) # plt.show() # cluster_assignments = fcluster(mergings, t=3.0, criterion='maxclust') # print(cluster_assignments) # for i in range(1,4): # print('cluster', i, ':') # num = 1 # for index, value in enumerate(cluster_assignments): # if value == i: # if num % 5 ==0: # print() # num+=1 # print(country[index],end=' ') # print()
原始数据分类后的聚簇:
cluster 1 : Pakistan Nigeria Bangladesh Ethiopia cluster 2 : United States Indonesia Brazil Russian Federation Japan Mexico Germany Turkey Thailand France United Kingdom cluster 3 : China India Philippines Vietnam Egypt, Arab Rep.
PCA降维后的分类聚簇:
cluster 1 : Pakistan Nigeria Bangladesh Ethiopia cluster 2 : China India Philippines Vietnam Egypt, Arab Rep. cluster 3 : United States Indonesia Brazil Russian Federation Japan Mexico Germany Turkey Thailand France United Kingdom
可以看出,分类结果都是一样的。
通过树状图对结果进行可视化
以下为建树数据(以原始数据为例):
[[18. 19. 0.21641882 2. ] [15. 20. 0.32365701 3. ] [ 2. 9. 0.39212766 2. ] [16. 21. 0.45344319 4. ] [ 8. 22. 0.50024778 3. ] [ 4. 10. 0.50648091 2. ] [13. 14. 0.51344362 2. ] [23. 24. 0.58762227 7. ] [ 3. 25. 0.58872577 3. ] [11. 26. 0.64184605 3. ] [ 5. 6. 0.71918707 2. ] [17. 28. 0.72310738 4. ] [ 0. 1. 0.84679303 2. ] [ 7. 12. 0.90714675 2. ] [30. 33. 0.97508395 4. ] [27. 31. 1.00112956 11. ] [29. 32. 1.15491503 5. ] [35. 36. 1.29675568 16. ] [34. 37. 1.76337101 20. ]]
对以上数据解析为:第一列和第二列为聚类簇编号;第三列为两个聚簇之间的距离;第四列为包含的聚簇数量。
其中聚簇间距离的计算为上文提到的第三种方法。原始数据树状图:
PCA降维后的结果:
-
Python实现的KMeans聚类算法实例分析
2021-01-20 05:50:53本文实例讲述了Python实现的KMeans聚类算法。分享给大家供大家参考,具体如下: 菜鸟一枚,编程初学者,最近想使用Python3实现几个简单的机器学习分析方法,记录一下自己的学习过程。 关于KMeans算法本身就不做介绍... -
原理+代码|详解层次聚类及Python实现
2020-12-01 10:24:00本文是Python商业数据挖掘实战的第6篇1 - 基于不平衡数据的反欺诈模型实战2 - Apriori算法实现智能推荐3- 随机森林预测宽带客户离网4 - 多元线性回归模型实战5 -P... -
Kmeans聚类算法,PCA降维,层次聚类算法,用Python实现
2019-07-05 10:26:54中科大2019春AI 实验二,包括Kmeans算法,PCA算法和层次聚类算法 -
层次聚类算法的原理及python实现
2018-01-05 11:27:52层次聚类(Hierarchical Clustering)是一种聚类算法,通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中,不同类别的原始数据点是树的最低层,树的顶层是一个聚类的根节点。 -
太强了,10种聚类算法完整Python实现!
2022-04-28 00:12:19来源:海豚数据科学实验室转自:数据分析1480今天给...有许多聚类算法可供选择,对于所有情况,没有单一的最佳聚类算法。相反,最好探索一系列聚类算法以及每种算法的不同配置。在本教程中,你将发现如何在 pytho... -
一文详解层次聚类(Python代码)
2022-03-15 22:26:31本篇想和大家介绍下层次聚类,先通过一个简单的例子介绍它的基本理论,然后再用一个实战案例Python代码实现聚类效果。首先要说,聚类属于机器学习的无监督学习,而且也分很多种方法,比如大家熟知的有K-means。层次... -
一文读懂层次聚类(Python代码)
2022-03-17 00:16:07本篇想和大家介绍下层次聚类,先通过一个简单的例子介绍它的基本理论,然后再用一个实战案例Python代码实现聚类效果。首先要说,聚类属于机器学习的无监督学习,而且也分很多种方法,比如大家熟知... -
python核心编程之Python聚类算法之凝聚层次聚类实例分析
2020-02-07 14:08:40这篇文章主要介绍了Python聚类算法之凝聚层次聚类的原理与具体使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例讲述了Python聚类算法之凝聚层次聚类。分享给大家供大家参考,具体如下: 凝聚层次聚类:... -
python实现AGNES(凝聚层次聚类)算法
2021-04-30 22:56:31#AGNES(凝聚层次聚类)算法 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.cluster import AgglomerativeClustering from sklearn import datasets from sklearn.metrics ... -
10 种 Python 聚类算法及python实现
2021-03-16 09:23:5310 种 Python 聚类算法及python实现 10 种 Python 聚类算法及python实现 聚类分析的定义 聚类分析是一种无监督的机器学习任务,从现有的数据实现对数据的自然分组,在特征空间中找到群组,只解释输入变量,不对数据... -
Python实现简单的层次聚类算法以及可视化
2019-01-25 21:46:27基本的算法思路就是:把当前组间距离最小的两组合并成一组。 算法的差异在算法如何确定组件的距离,一般有最大距离,最小距离,平均距离,马氏距离等等。 代码如下: import numpy as np import data_helper np.... -
聚类算法总结以及python代码实现
2020-12-02 13:44:14二、层次聚类层次聚类算法实际上分为两类:自上而下或自下而上。自下而上的算法在一开始就将每个数据点视为一个单一的聚类,然后依次合并(或聚集)类,直到所有类合并成一个包含所有数据点的单一聚类。因此,自下而上...