• 层次聚类及scipy中的层次聚类python代码解释
2022-01-25 14:02:24

层次聚类假设类别之间存在层次结构，将样本聚到层次化的类中。层次聚类分为自下而上、自上而下聚类的两种方法。由于每个样本只能属于一个类别，因此层次聚类属于硬聚类。

基本原理（本文只讲述自下而上的聚合方法）：

1. 聚类前数据各自属于一个类
2. 计算各个数据之间的距离，将相距最近的两类合并（当类中有许多数据时，存在距离最小的数据组即可实现两类合并），建立一个新的类
3. 反复进行2直到最后合并成只剩一个类
可以看出聚合参差聚类算法的复杂度时O(n^3 * m)其中n为样本的个数，m为样本的维数。

scipy中的两个函数即可完成此任务。

metric的参数

    metric : str or function, optional
The distance metric to use. The distance function can
be 'braycurtis', 'canberra', 'chebyshev', 'cityblock',
'correlation', 'cosine', 'dice', 'euclidean', 'hamming',
'jaccard', 'jensenshannon', 'kulsinski', 'mahalanobis', 'matching',
'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean',
'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule'.


methord的参数

* method='single' assigns

.. math::
d(u,v) = \\min(dist(u[i],v[j]))

for all points :math:i in cluster :math:u and
:math:j in cluster :math:v. This is also known as the
Nearest Point Algorithm.

* method='complete' assigns

.. math::
d(u, v) = \\max(dist(u[i],v[j]))

for all points :math:i in cluster u and :math:j in
cluster :math:v. This is also known by the Farthest Point
Algorithm or Voor Hees Algorithm.

* method='average' assigns

.. math::
d(u,v) = \\sum_{ij} \\frac{d(u[i], v[j])}
{(|u|*|v|)}

for all points :math:i and :math:j where :math:|u|
and :math:|v| are the cardinalities of clusters :math:u
and :math:v, respectively. This is also called the UPGMA
algorithm.

* method='weighted' assigns

.. math::
d(u,v) = (dist(s,v) + dist(t,v))/2

where cluster u was formed with cluster s and t and v
is a remaining cluster in the forest (also called WPGMA).

* method='centroid' assigns

.. math::
dist(s,t) = ||c_s-c_t||_2

where :math:c_s and :math:c_t are the centroids of
clusters :math:s and :math:t, respectively. When two
clusters :math:s and :math:t are combined into a new
cluster :math:u, the new centroid is computed over all the
original objects in clusters :math:s and :math:t. The
distance then becomes the Euclidean distance between the
centroid of :math:u and the centroid of a remaining cluster
:math:v in the forest. This is also known as the UPGMC
algorithm.

* method='median' assigns :math:d(s,t) like the centroid
method. When two clusters :math:s and :math:t are combined
into a new cluster :math:u, the average of centroids s and t
give the new centroid :math:u. This is also known as the
WPGMC algorithm.

* method='ward' uses the Ward variance minimization algorithm.
The new entry :math:d(u,v) is computed as follows,

.. math::

d(u,v) = \\sqrt{\\frac{|v|+|s|}
{T}d(v,s)^2
+ \\frac{|v|+|t|}
{T}d(v,t)^2
- \\frac{|v|}
{T}d(s,t)^2}

where :math:u is the newly joined cluster consisting of
clusters :math:s and :math:t, :math:v is an unused
cluster in the forest, :math:T=|v|+|s|+|t|, and
:math:|*| is the cardinality of its argument. This is also
known as the incremental algorithm.


scipy.cluster.hierarchy.dendrogram(Z, labels=label, above_threshold_color=‘C0’)主要用于画层次聚类图

完整代码如下：

from matplotlib import pyplot as plt
from scipy.cluster import hierarchy  # 层次聚类
import matplotlib as mpl

mpl.rcParams['font.sans-serif'] = ['FangSong']  # 指定中文字体
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

data = iris.data
label = iris.target

fig = plt.subplots(1, 1, figsize=(50, 8))  # figsize为画布大小
Z = hierarchy.linkage(data, method='average', metric="euclidean")  # 计算合并类的方法，这里是取平均距离,距离用的是欧氏距离
hierarchy.dendrogram(Z, labels=label, above_threshold_color='C0')  # 画层次聚类图
plt.plot(linewidth=1.0)
plt.xticks(fontsize=14, rotation=0)  # x轴标签字体大小与方向调整
plt.rcParams['savefig.dpi'] = 200  # 图片像素
plt.rcParams['figure.dpi'] = 200  # 分辨率
plt.tight_layout()  # 自动调整子图参数，使之填充整个图像区域
plt.savefig("H_iris.png", dpi=100, bbox_inches='tight')  # 保存图片
plt.show()



用的数据为鸢尾花数据集，可见0和1、2之间的区别是非常明确的，1、2之间的区分也是能够明显看的出来的，

更多相关内容
• 本文实例为大家分享了Python实现简单层次聚类算法，以及可视化，供大家参考，具体内容如下 基本的算法思路就是：把当前组间距离最小的两组合并成一组。 算法的差异在算法如何确定组件的距离，一般有最大距离，最小...
• ## 层次聚类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 = 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")
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")
# 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 :
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 :
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聚类算法之凝聚层次聚类的原理与具体使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
• 本篇想和大家介绍下层次聚类，先通过一个简单的例子介绍它的基本理论，然后再用一个实战案例Python代码实现聚类效果。首先要说，聚类属于机器学习的无监督学习，而且也分很多种方法，比如大家熟知...

本篇想和大家介绍下层次聚类，先通过一个简单的例子介绍它的基本理论，然后再用一个实战案例Python代码实现聚类效果。

首先要说，聚类属于机器学习的无监督学习，而且也分很多种方法，比如大家熟知的有K-means。层次聚类也是聚类中的一种，也很常用。下面我先简单回顾一下K-means的基本原理，然后慢慢引出层次聚类的定义和分层步骤，这样更有助于大家理解。

## 层次聚类和K-means有什么不同？

K-means 工作原理可以简要概述为：

• 决定簇数（k）

• 从数据中随机选取 k 个点作为质心

• 将所有点分配到最近的聚类质心

• 计算新形成的簇的质心

• 重复步骤 3 和 4

这是一个迭代过程，直到新形成的簇的质心不变，或者达到最大迭代次数。

但是 K-means 是存在一些缺点的，我们必须在算法开始前就决定簇数 K 的数量，但实际我们并不知道应该有多少个簇，所以一般都是根据自己的理解先设定一个值，这就可能导致我们的理解和实际情况存在一些偏差。

层次聚类完全不同，它不需要我们开始的时候指定簇数，而是先完整的形成整个层次聚类后，通过决定合适的距离，自动就可以找到对应的簇数和聚类。

## 什么是层次聚类？

下面我们由浅及深的介绍什么是层次聚类，先来一个简单的例子。

假设我们有以下几点，我们想将它们分组：

我们可以将这些点中的每一个分配给一个单独的簇，就是4个簇（4种颜色）：

然后基于这些簇的相似性（距离），将最相似的（距离最近的）点组合在一起并重复这个过程，直到只剩下一个集群：

上面本质上就是在构建一个层次结构。先了解到这里，后面我们详细介绍它的分层步骤。

## 层次聚类的类型

主要有两种类型的层次聚类：

• 凝聚层次聚类

• 分裂层次聚类

### 凝聚层次聚类

先让所有点分别成为一个单独的簇，然后通过相似性不断组合，直到最后只有一个簇为止，这就是凝聚层次聚类的过程，和我们上面刚刚说的一致。

### 分裂层次聚类

分裂层次聚类正好反过来，它是从单个集群开始逐步分裂，直到无法分裂，即每个点都是一个簇。

所以无论是 10、100、1000 个数据点都不重要，这些点在开始的时候都属于同一个簇：

现在，在每次迭代中拆分簇中相隔最远的两点，并重复这个过程，直到每个簇只包含一个点：

上面的过程就是分裂层次聚类

## 执行层次聚类的步骤

上面已经说了层次聚类的大概过程，那关键的来了，如何确定点和点的相似性呢？

这是聚类中最重要的问题之一了，一般计算相似度的方法是：计算这些簇的质心之间的距离。距离最小的点称为相似点，我们可以合并它们，也可以将其称为基于距离的算法

另外在层次聚类中，还有一个称为邻近矩阵的概念，它存储了每个点之间的距离。下面我们通过一个例子来理解如何计算相似度、邻近矩阵、以及层次聚类的具体步骤。

### 案例介绍

假设一位老师想要将学生分成不同的组。现在有每个学生在作业中的分数，想根据这些分数将他们分成几组。关于拥有多少组，这里没有固定的目标。由于老师不知道应该将哪种类型的学生分配到哪个组，因此不能作为监督学习问题来解决。下面，我们将尝试应用层次聚类将学生分成不同的组。

下面是个5名学生的成绩：

### 创建邻近矩阵

首先，我们要创建一个邻近矩阵，它储存了每个点两两之间的距离，因此可以得到一个形状为 n X n 的方阵。

这个案例中，可以得到以下 5 x 5 的邻近矩阵：

矩阵里有两点需要注意下：

• 矩阵的对角元素始终为 0，因为点与其自身的距离始终为 0

• 使用欧几里得距离公式来计算非对角元素的距离

比如，我们要计算点 1 和 2 之间的距离，计算公式为：

同理，按此计算方法完成后填充邻近矩阵其余元素。

### 执行层次聚类

这里使用凝聚层次聚类来实现。

步骤 1：首先，我们将所有点分配成单个簇：

这里不同的颜色代表不同的簇，我们数据中的 5 个点，即有 5 个不同的簇。

步骤2：接下来，我们需要查找邻近矩阵中的最小距离并合并距离最小的点。然后我们更新邻近矩阵：最小距离是 3，因此我们将合并点 1 和 2：让我们看看更新的集群并相应地更新邻近矩阵：

更新之后，我们取了1、2 两个点中值 (7, 10) 最大的来替换这个簇的值。当然除了最大值之外，我们还可以取最小值或平均值。然后，我们将再次计算这些簇的邻近矩阵：第 3 步：重复第 2 步，直到只剩下一个簇。

重复所有的步骤后，我们将得到如下所示的合并的聚类：

这就是凝聚层次聚类的工作原理。但问题是我们仍然不知道该分几组？是2、3、还是4组呢？

下面开始介绍如何选择聚类数。

## 如何选择聚类数？

为了获得层次聚类的簇数，我们使用了一个概念，叫作树状图

通过树状图，我们可以更方便的选出聚类的簇数。

回到上面的例子。当我们合并两个簇时，树状图会相应地记录这些簇之间的距离并以图形形式表示。下面这个是树状图的原始状态，横坐标记录了每个点的标记，纵轴记录了点和点之间的距离：

当合并两个簇时，将会在树状图中连接起来，连接的高度就是点之间的距离。下面是我们刚刚层次聚类的过程。

然后开始对上面的过程进行树状图的绘制。从合并样本 1 和 2 开始，这两个样本之间的距离为 3。

可以看到已经合并了 1 和 2。垂直线代表 1 和 2 的距离。同理，按照层次聚类过程绘制合并簇类的所有步骤，最后得到了这样的树状图：

通过树状图，我们可以清楚地形象化层次聚类的步骤。树状图中垂直线的距离越远代表簇之间的距离越大。

有了这个树状图，我们决定簇类数就方便多了。

现在我们可以设置一个阈值距离，绘制一条水平线。比如我们将阈值设置为 12，并绘制一条水平线，如下：

从交点中可以看到，聚类的数量就是与阈值水平线与垂直线相交的数量（红线与 2 条垂直线相交，我们将有 2 个簇）。与横坐标相对应的，一个簇将有一个样本集合为 (1,2,4)，另一个集群将有一个样本集合 (3,5)。

这样，我们就通过树状图解决了分层聚类中要决定聚类的数量。

## Python代码实战案例

上面是理论基础，有点数学基础都能看懂。下面介绍下在如何用代码Python来实现这一过程。这里拿一个客户细分的数据来展示一下。

数据集和代码在我的GitHub里，欢迎star！

https://github.com/xiaoyusmd/PythonDataScience

这个数据来源于UCI 机器学习库。我们的目的是根据批发分销商的客户在不同产品类别（如牛奶、杂货、地区等）上的年度支出，对他们进行细分。

首先对数据进行一个标准化，为了让所有数据在同一个维度便于计算，然后应用层次聚类来细分客户。

from sklearn.preprocessing import normalize
data_scaled = normalize(data)
data_scaled = pd.DataFrame(data_scaled, columns=data.columns)

import scipy.cluster.hierarchy as shc
plt.figure(figsize=(10, 7))
plt.title("Dendrograms")
dend = shc.dendrogram(shc.linkage(data_scaled, method='ward'))

x 轴包含了所有样本，y 轴代表这些样本之间的距离。距离最大的垂直线是蓝线，假如我们决定要以阈值 6 切割树状图：

plt.figure(figsize=(10, 7))
plt.title("Dendrograms")
plt.axhline(y=6, color='r', linestyle='--')

现在我们有两个簇了，我们要对这 2 个簇应用层次聚类：

from sklearn.cluster import AgglomerativeClustering
cluster.fit_predict(data_scaled)

由于我们定义了 2 个簇，因此我们可以在输出中看到 0 和 1 的值。0 代表属于第一个簇的点，1 代表属于第二个簇的点。

plt.figure(figsize=(10, 7))
plt.scatter(data_scaled['Milk'], data_scaled['Grocery'], c=cluster.labels_)

到这里我们就成功的完成了聚类。

参考：https://www.analyticsvidhya.com/blog/2019/05/beginners-guide-hierarchical-clustering/

END -

对比Excel系列图书累积销量达15w册，让你轻松掌握数据分析技能，可以在全网搜索书名进行了解：
展开全文
• 本篇想和大家介绍下层次聚类，先通过一个简单的例子介绍它的基本理论，然后再用一个实战案例Python代码实现聚类效果。首先要说，聚类属于机器学习的无监督学习，而且也分很多种方法，比如大家熟知的有K-means。层次...

本篇想和大家介绍下层次聚类，先通过一个简单的例子介绍它的基本理论，然后再用一个实战案例Python代码实现聚类效果。

首先要说，聚类属于机器学习的无监督学习，而且也分很多种方法，比如大家熟知的有K-means。层次聚类也是聚类中的一种，也很常用。下面我先简单回顾一下K-means的基本原理，然后慢慢引出层次聚类的定义和分层步骤，这样更有助于大家理解。

## 层次聚类和K-means有什么不同？

K-means 工作原理可以简要概述为：

• 决定簇数（k）

• 从数据中随机选取 k 个点作为质心

• 将所有点分配到最近的聚类质心

• 计算新形成的簇的质心

• 重复步骤 3 和 4

这是一个迭代过程，直到新形成的簇的质心不变，或者达到最大迭代次数。

但是 K-means 是存在一些缺点的，我们必须在算法开始前就决定簇数 K 的数量，但实际我们并不知道应该有多少个簇，所以一般都是根据自己的理解先设定一个值，这就可能导致我们的理解和实际情况存在一些偏差。

层次聚类完全不同，它不需要我们开始的时候指定簇数，而是先完整的形成整个层次聚类后，通过决定合适的距离，自动就可以找到对应的簇数和聚类。

## 什么是层次聚类？

下面我们由浅及深的介绍什么是层次聚类，先来一个简单的例子。

假设我们有以下几点，我们想将它们分组：

我们可以将这些点中的每一个分配给一个单独的簇，就是4个簇（4种颜色）：

然后基于这些簇的相似性（距离），将最相似的（距离最近的）点组合在一起并重复这个过程，直到只剩下一个集群：

上面本质上就是在构建一个层次结构。先了解到这里，后面我们详细介绍它的分层步骤。

## 层次聚类的类型

主要有两种类型的层次聚类：

• 凝聚层次聚类

• 分裂层次聚类

### 凝聚层次聚类

先让所有点分别成为一个单独的簇，然后通过相似性不断组合，直到最后只有一个簇为止，这就是凝聚层次聚类的过程，和我们上面刚刚说的一致。

### 分裂层次聚类

分裂层次聚类正好反过来，它是从单个集群开始逐步分裂，直到无法分裂，即每个点都是一个簇。

所以无论是 10、100、1000 个数据点都不重要，这些点在开始的时候都属于同一个簇：

现在，在每次迭代中拆分簇中相隔最远的两点，并重复这个过程，直到每个簇只包含一个点：

上面的过程就是分裂层次聚类

## 执行层次聚类的步骤

上面已经说了层次聚类的大概过程，那关键的来了，如何确定点和点的相似性呢？

这是聚类中最重要的问题之一了，一般计算相似度的方法是：计算这些簇的质心之间的距离。距离最小的点称为相似点，我们可以合并它们，也可以将其称为基于距离的算法

另外在层次聚类中，还有一个称为邻近矩阵的概念，它存储了每个点之间的距离。下面我们通过一个例子来理解如何计算相似度、邻近矩阵、以及层次聚类的具体步骤。

### 案例介绍

假设一位老师想要将学生分成不同的组。现在有每个学生在作业中的分数，想根据这些分数将他们分成几组。关于拥有多少组，这里没有固定的目标。由于老师不知道应该将哪种类型的学生分配到哪个组，因此不能作为监督学习问题来解决。下面，我们将尝试应用层次聚类将学生分成不同的组。

下面是个5名学生的成绩：

### 创建邻近矩阵

首先，我们要创建一个邻近矩阵，它储存了每个点两两之间的距离，因此可以得到一个形状为 n X n 的方阵。

这个案例中，可以得到以下 5 x 5 的邻近矩阵：

矩阵里有两点需要注意下：

• 矩阵的对角元素始终为 0，因为点与其自身的距离始终为 0

• 使用欧几里得距离公式来计算非对角元素的距离

比如，我们要计算点 1 和 2 之间的距离，计算公式为：

同理，按此计算方法完成后填充邻近矩阵其余元素。

### 执行层次聚类

这里使用凝聚层次聚类来实现。

步骤 1：首先，我们将所有点分配成单个簇：

这里不同的颜色代表不同的簇，我们数据中的 5 个点，即有 5 个不同的簇。

步骤2：接下来，我们需要查找邻近矩阵中的最小距离并合并距离最小的点。然后我们更新邻近矩阵：最小距离是 3，因此我们将合并点 1 和 2：让我们看看更新的集群并相应地更新邻近矩阵：

更新之后，我们取了1、2 两个点中值 (7, 10) 最大的来替换这个簇的值。当然除了最大值之外，我们还可以取最小值或平均值。然后，我们将再次计算这些簇的邻近矩阵：第 3 步：重复第 2 步，直到只剩下一个簇。

重复所有的步骤后，我们将得到如下所示的合并的聚类：

这就是凝聚层次聚类的工作原理。但问题是我们仍然不知道该分几组？是2、3、还是4组呢？

下面开始介绍如何选择聚类数。

## 如何选择聚类数？

为了获得层次聚类的簇数，我们使用了一个概念，叫作树状图

通过树状图，我们可以更方便的选出聚类的簇数。

回到上面的例子。当我们合并两个簇时，树状图会相应地记录这些簇之间的距离并以图形形式表示。下面这个是树状图的原始状态，横坐标记录了每个点的标记，纵轴记录了点和点之间的距离：

当合并两个簇时，将会在树状图中连接起来，连接的高度就是点之间的距离。下面是我们刚刚层次聚类的过程。

然后开始对上面的过程进行树状图的绘制。从合并样本 1 和 2 开始，这两个样本之间的距离为 3。

可以看到已经合并了 1 和 2。垂直线代表 1 和 2 的距离。同理，按照层次聚类过程绘制合并簇类的所有步骤，最后得到了这样的树状图：

通过树状图，我们可以清楚地形象化层次聚类的步骤。树状图中垂直线的距离越远代表簇之间的距离越大。

有了这个树状图，我们决定簇类数就方便多了。

现在我们可以设置一个阈值距离，绘制一条水平线。比如我们将阈值设置为 12，并绘制一条水平线，如下：

从交点中可以看到，聚类的数量就是与阈值水平线与垂直线相交的数量（红线与 2 条垂直线相交，我们将有 2 个簇）。与横坐标相对应的，一个簇将有一个样本集合为 (1,2,4)，另一个集群将有一个样本集合 (3,5)。

这样，我们就通过树状图解决了分层聚类中要决定聚类的数量。

## Python代码实战案例

上面是理论基础，有点数学基础都能看懂。下面介绍下在如何用代码Python来实现这一过程。这里拿一个客户细分的数据来展示一下。需要数据文末找我获取

这个数据来源于UCI 机器学习库。我们的目的是根据批发分销商的客户在不同产品类别（如牛奶、杂货、地区等）上的年度支出，对他们进行细分。

首先对数据进行一个标准化，为了让所有数据在同一个维度便于计算，然后应用层次聚类来细分客户。

from sklearn.preprocessing import normalize
data_scaled = normalize(data)
data_scaled = pd.DataFrame(data_scaled, columns=data.columns)

import scipy.cluster.hierarchy as shc
plt.figure(figsize=(10, 7))
plt.title("Dendrograms")


x 轴包含了所有样本，y 轴代表这些样本之间的距离。距离最大的垂直线是蓝线，假如我们决定要以阈值 6 切割树状图：

plt.figure(figsize=(10, 7))
plt.title("Dendrograms")
plt.axhline(y=6, color='r', linestyle='--')


现在我们有两个簇了，我们要对这 2 个簇应用层次聚类：

from sklearn.cluster import AgglomerativeClustering
cluster.fit_predict(data_scaled)


由于我们定义了 2 个簇，因此我们可以在输出中看到 0 和 1 的值。0 代表属于第一个簇的点，1 代表属于第二个簇的点。

plt.figure(figsize=(10, 7))
plt.scatter(data_scaled['Milk'], data_scaled['Grocery'], c=cluster.labels_)


到这里我们就成功的完成了聚类。

## 技术交流

欢迎转载、收藏、有所收获点赞支持一下！

目前开通了面试技术交流群，群友已超过2000人，添加时最好的备注方式为：来源+兴趣方向，方便找到志同道合的朋友

• 方式①、发送如下图片至微信，长按识别，后台回复：加群；
• 方式②、添加微信号：dkl88191，备注：来自CSDN
• 方式③、微信搜索公众号：Python学习与数据挖掘，后台回复：加群

展开全文
• BAFIMINARMTO BA0662877255412996 FI6620295468268400 MI8772950754564138 NA2554687540219869 RM4122685642190669 TO9964001388696690 这是... scipy里面关于层次聚类的函数还有不少，我也没有搞懂，这里就不多说了。
• 凝聚层次聚类层次聚类方法凝聚层次聚类算法原理簇间距离计算方法单链法single全链法complete组平均法 averageward法python代码实现绘制层次聚类树状图一些参考 相关文章： 数据挖掘 | [关联规则] 利用apyori库的关联...
• 层次聚类(AGNES)算法(Python) 是聚类算法的一种，通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树。在聚类树中，不同类别的原始数据点是树的最低层，树的顶层是一个聚类的根节点。AGNES是常用的一种...
• 前言聚类分析是研究分类问题的分析方法，是洞察用户偏好和做用户画像的利器之一。...本文将详细介绍如何 利用 Python 实现基于层次聚类的客户分群，主要分为两个部分：层次聚类详细原理介绍Python ...
• 本篇和大家介绍下层次聚类，先通过一个简单的例子介绍它的基本理论，然后再用一个实战案例Python代码实现聚类效果。首先要说，聚类属于机器学习的无监督学习，而且也分很多种方法，比如大家熟知的...
• 二、层次聚类层次聚类算法实际上分为两类：自上而下或自下而上。自下而上的算法在一开始就将每个数据点视为一个单一的聚类，然后依次合并(或聚集)类，直到所有类合并成一个包含所有数据点的单一聚类。因此，自下而上...
• 广告关闭腾讯云11.11云上盛惠 ，精选... 层次聚类分为两种：合并（自下而上）聚类(agglomerative)分裂（自上而下）聚类(divisive)目前使用较多的是合并聚类 ，本文着重讲解合并聚类的原理。 agens层次聚类原理合并聚...
• 聚类算法及python实现——层次聚类 构建二叉树 步骤 step1：将每个样品都看作一类 step2：计算每个样品两两之间的距离 step3：合并距离最近的两类变成一个新的类 step4：计算各个类之间的距离，合并，直至只有一类 ...
• from scipy.cluster import hierarchy0.层次聚类的概念层次聚类和k-means一样都是很常用的聚类方法。...层次聚类又分为自底而上的聚合层次聚类和自顶而下的分裂层次聚类。0.1 聚合层次聚类每一个点初始为1类，得到N(...
• 层次聚类(hierarchical clustering)可在不同层次上对数据集进行划分，形成树状的聚类结构。AggregativeClustering是一种常用的层次聚类算法。其原理是：最初将每个对象看成一个簇，然后将这些簇根据某种规则被一步步...
• 层次聚类(Hierarchical Clustering)一.概念层次聚类不需要指定聚类的数目，首先它是将数据中的每个实例看作一个类，然后将最相似的两个类合并，该过程迭代计算只到剩下一个类为止，类由两个子类构成，每个子类又由更...
• 这些是文本聚类算法的一些实现，尽管只有增量层次凝聚聚类 (IHAC) 的实现已经完善和完成。 这个项目是专门为组合起来的，所以一些设置是为此量身定制的，尽管我最终希望让它更通用一些。 设置 您需要为 Pytables（ ...
• 运用python进行层次聚类 学习scipy库 很重要呀 需要引入的类 import scipy.cluster.hierarchy as sch 我们使用的原始数据如下 X= [[2], [8], [0], [4], [1], [9], [9], [0]] 接下来的一些代码如下： Y = sch....
• 0.层次聚类的概念 层次聚类和k-means一样都是很常用的聚类方法。...关于层次聚类算法的python实现 - 简书 (jianshu.com)https://www.jianshu.com/p/916aab25cda7 0.1 聚合层次聚类 每一个点初始为1类，得到N(样本
• 层次聚类 层次聚类，顾名思义，就是一层一层的进行聚类，它试图在不同层次对数据集进行划分，可以由上向下把大的类别分割，即“自顶向下”的分拆策略(见下面AGNES部分)，也可以由下向上对小的类别进行聚合，即“自...
• 使用python实现中文文本聚类，利用kmeans算法，包含jiba分词方法等

...