[译] 层次聚类的初学者指南(用 Python 实现)

栏目: 编程工具 · 发布时间: 5年前

内容简介:原文选自 | analyticsvidhya作者 | Pulkit Sharma全文约4700字,推荐阅读时间7分钟

原文选自 | analyticsvidhya

作者 | Pulkit Sharma

全文约4700字,推荐阅读时间7分钟

点击【阅读原文】可查看英文原文

介绍

任何行业中,了解客户行为都是至关重要的。去年,我的首席营销官问 “现有客户中哪些客户应作为新产品的目标用户?”时,我就意识到了这一点。

对我来说,这是一个很好的学习曲线。我意识到了细分客户是多么重要,这样企业就可以制定和构建针对性策略。聚类的概念在这里变得非常方便!

像细分客户这样的问题通常很棘手,因为我们没有任何目标变量供考虑。我们处在一个无监督学习的状态,需要从中找出模式和结构,而不用考虑一个既定的结果。作为一名数据科学家,这既具有挑战又令人兴奋。

[译] 层次聚类的初学者指南(用  <a href='https://www.codercto.com/topics/20097.html'>Python</a>  实现)

有几种不同的方法可以执行聚类(如下所示)。我将在本文中向您介绍其中一种--层次聚类。

我们将了解层次聚类是什么,它优于其他聚类算法的优势,不同类型的层次聚类以及执行它的步骤。我们最终使用客户细分数据集在Python中实现层次聚类。我很喜欢这种技术,我相信你也会在看完这篇文章之后做到这一点!

注意:如上所述,有多种方法可以执行群集。我鼓励您在文末链接查看介绍不同类型群集的精彩指南。

目录

  1. 监督学习与无监督学习

  2. 为什么采用层次聚类

  3. 什么是层次聚类

  4. 层次聚类的类型

    1. 聚合层次聚类

    2. 分裂层次聚类

  5. 执行层次聚类的步骤

  6. 如何选择层次聚类中的聚类数

  7. 使用层次聚类解决客户细分问题

监督学习与非监督学习

在深入层次聚类之前,理解有监督和无监督学习之间的区别非常重要。让我用一个简单的例子解释这个差异。

假设我们想要估算每天在城市租用的自行车数量:

[译] 层次聚类的初学者指南(用 Python 实现)

或者假设我们想要预测泰坦尼克号上的人是否幸存:

[译] 层次聚类的初学者指南(用 Python 实现)

我们在这两个示例中都有一个固定的目标:

  • 在第一个例子中,我们必须根据季节,假日,工作日,天气,气温等特征预测自行车的数量。

  • 我们在第二个例子中预测乘客是否幸存。在'Survived'变量中,0代表该人丧生,1代表该人幸存。这里的自变量包括船票等级,性别,年龄等。

因此,当我们给出一个目标变量(上述两种情况下的数量和生存情况)时,我们必须根据给定的一组预测变量或自变量(季节,假日,性别,年龄等)进行预测,这些问题称为监督学习问题。

让我们从下图直观地理解这一点:

[译] 层次聚类的初学者指南(用 Python 实现)

这里y是我们的依赖变量,或叫做目标变量,X代表自变量。目标变量依赖于X,因此它也被称为因变量。我们使用自变量在目标变量的监督下训练我们的模型,因此命名为监督学习。

在训练模型时,我们的目标是生成将自变量映射到所需目标的函数。一旦模型被训练,模型就可以通过新的观测值预测它们的目标。简而言之,这是有监督的学习。

但是可能存在我们没有任何目标变量来预测的情况。没有任何明确的目标变量的这些问题被称为无监督学习问题。我们在这些问题中只有自变量而没有目标/因变量。

[译] 层次聚类的初学者指南(用 Python 实现)

在这些情况下,我们尝试将整个数据划分为一些组。这些组称为集群,制作这些集群的过程称为聚类。

[译] 层次聚类的初学者指南(用 Python 实现)

该技术通常用于将群体聚类到不同的群组中。一些常见示例包括细分客户,将文档归类在一起,推荐相似的歌曲或电影等。

有许多无监督学习的应用。如果您遇到任何有趣的应用程序,请随时在下面的评论部分分享!

现在,有各种算法可以帮助我们划分这些集群。最常用的聚类算法是K-means和Hierarchical clustering(层次聚类)。

为什么使用层次聚类

在我们深入层次聚类之前,我们应该先了解K-means的工作原理。相信我,它将使层次聚类的概念变得更加容易。

以下是K-means工作原理的概述:

  1. 确定簇数(k)

  2. 从数据中选择k个随机点作为质心

  3. 将所有点分配到最近的簇的质心

  4. 计算新形成的簇的质心

  5. 重复步骤3和4

这是一个迭代过程。它将继续运行,直到新形成的簇的质心不再变化或达到最大迭代次数。

但K-means存在一定的挑战。因为它总是试图将集群划分为相同大小。此外,我们必须在算法开始时确定簇的数量。理想情况下,我们不知道算法的一开始应该有多少个簇,因此它是K-means的挑战。

这就平稳的过渡到了层次聚类。它消除了必须预先定义集群数量的问题。听起来像在做梦!那么,让我们看看什么是层次聚类,以及它如何改进k-means。

什么是层次聚类

假设我们有以下几个点,我们希望将它们分组:

[译] 层次聚类的初学者指南(用 Python 实现)

我们可以将每个点分配给一个单独的集群:

[译] 层次聚类的初学者指南(用 Python 实现)

现在,基于这些集群的相似性,我们可以将最相似的集群组合在一起并重复此过程,直到只留下一个集群:

[译] 层次聚类的初学者指南(用 Python 实现)

我们这是在构建集群层次结构。这就是为什么这个算法被称为层次聚类。我将在后面的部分讨论如何确定集群的数量。现在,让我们看看不同类型的层次聚类。

层次聚类的类型

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

  1. 聚合层次聚类

  2. 分裂层次聚类

让我们来详细了解一下每种类型。

聚合层次聚类

我们在这种技术中,将每个点分配给一个单独的集群。假设有4个数据点。我们将每个点分配给一个集群,因此在开始时将有4个集群:

[译] 层次聚类的初学者指南(用 Python 实现)

然后,在每次迭代时,我们合并最近的一对集群并重复此步骤,直到只留下一个簇:

[译] 层次聚类的初学者指南(用 Python 实现)

我们在每一步合并(或添加)集群,对吧?因此,这种类型的聚类也称为加和层次聚类。

分裂层次聚类

分裂层次聚类以相反的方式工作。我们不是从n个集群开始(在n个观察的情况下),而是从单个集群开始,并将所有点分配给该集群。

因此,如果我们有10或1000个数据点,都无关紧要。所有这些点在开始时都属于同一个集群:

[译] 层次聚类的初学者指南(用 Python 实现)

现在,在每次迭代中,我们分离集群中的最远点并重复此过程,直到每个集群仅包含一个点:

[译] 层次聚类的初学者指南(用 Python 实现)

我们在每一步进行分裂(或划分)集群,因此称为分裂层次聚类。

聚合聚类在业界广泛使用,这将成为本文的重点。一旦我们处理了聚合型,分裂的层次聚类就像一块蛋糕一样。

执行层次聚类的步骤

我们在层次聚类中合并最相似的点或集群--这是我们已知的。现在的问题是 - 我们如何确定哪些点相似,哪些不相似?这是聚类中最重要的问题之一!

计算相似度的方法之一是获取这些集群质心之间的距离。具有最小距离的点被称为相似点,我们可以合并它们。这被称为基于距离的算法(因为我们正在计算集群之间的距离)。

在层次聚类中,有一个被称为邻近矩阵的概念。它存储了每个点之间的距离。让我们举一个例子来理解这个矩阵以及执行层次聚类的步骤。

示例

[译] 层次聚类的初学者指南(用 Python 实现)

假设一位老师想把她的学生分成不同的小组。她有每个学生的作业得分,她希望根据这些分数给学生分组(这里没有固定要多少组的目标)。由于教师不知道应该将哪种类型的学生分配到哪个小组,所以不能将其作为监督学习问题解决。我们将尝试在此处应用层次聚类,并将学生划分为不同的组。

我们来看看5名学生的样本:

[译] 层次聚类的初学者指南(用 Python 实现)

创建邻近矩阵

首先,我们将创建一个邻近矩阵,它将告诉我们每个点之间的距离。我们计算了每个点与每个其他点的距离,得到一个形状为n X n的方形矩阵(其中n是观测数)。

制作5 x 5邻近矩阵:

[译] 层次聚类的初学者指南(用 Python 实现)

此矩阵的对角线元素将始终为0,因为点与其自身的距离始终为0。使用欧几里德距离公式计算其余距离。假设我们想要计算第1点和第2点之间的距离:

√(10-7)^ 2 =√9= 3

同样,我们可以计算所有距离并填充邻近矩阵。

执行层次聚类的步骤

第1步: 首先,将所有点分配给单个集群:

[译] 层次聚类的初学者指南(用 Python 实现)

这里不同的颜色代表不同的聚类。您可以看到有5个点,对应5个不同的聚类。

第2步:   接下来,我们将查看邻近矩阵中的最小距离,合并具有最小距离的点。然后更新邻近矩阵:

[译] 层次聚类的初学者指南(用 Python 实现)

这里,最小距离是3,因此我们将合并第1点和第2点:

[译] 层次聚类的初学者指南(用 Python 实现)

让我们看一下更新的集群,并相应地更新邻近矩阵:

[译] 层次聚类的初学者指南(用 Python 实现)

这里取了两个标记(7,10)的最大值来替换该集群的标记。也可以取最小值或平均值,而不是最大值。现在,我们将再次计算这些集群的邻近矩阵:

[译] 层次聚类的初学者指南(用 Python 实现)

第3步: 我们将重复步骤2,直到只剩下一个集群。

首先查看邻近矩阵中的最小距离,然后合并最近的一对集群。重复这些步骤后,我们将获得如下所示的合并集群:

[译] 层次聚类的初学者指南(用 Python 实现)

我们从5个集群开始,最后只有一个集群。这就是聚合层次聚类的工作原理。但问题仍然存在---我们如何决定集群的数量?让我们在下一节中介绍。

如何选择层次聚类中的聚类数

准备好回答这个自从开始学习以来就一直存在的问题了吗?为了获得用于层次聚类的聚类数量,我们使用了一种叫做树图的令人敬畏的概念。

树图是一种树状图,记录合并或分裂的序列。

让我们回到师生示例。每当合并两个聚类时,树图将记录这些聚类之间的距离并以图形表示。我们来看看树状图是怎样的:

[译] 层次聚类的初学者指南(用 Python 实现)

我们在x轴上有数据集的样本,在y轴上有距离。每当合并两个集群时,我们将在这个树图中加入它们,并且连接的高度将是这些点之间的距离。接下来我们来构建树图:

[译] 层次聚类的初学者指南(用 Python 实现)

下面花点时间处理上面的图像。我们首先合并样本1和2,这两个样本之间的距离为3(参考上一节中的第一个邻近矩阵)。让我们在树图中绘制这个:

[译] 层次聚类的初学者指南(用 Python 实现)

合并了样本1和2。垂直线表示这些样本之间的距离。同样,我们绘制了合并聚类的所有步骤,最后,我们得到了这样的树图:

[译] 层次聚类的初学者指南(用 Python 实现)

我们可以清楚地看到层次聚类的步骤。树形图中垂直线的距离越大,这些集群之间的距离就越大。

现在,我们可以设置一个阈值距离并绘制一条水平线(通常,设置阈值使其截断最高的垂直线)。我们将此阈值设置为12并绘制一条水平线:

[译] 层次聚类的初学者指南(用 Python 实现)

集群的数量将是与使用阈值绘制的线相交的垂直线的数量。在上面的例子中,由于红线与2条垂直线相交,我们将有2个簇。一个集群将有一个样本(1,2,4),另一个集群将有一个样本(3,5)。很简单,对吧?

这就是我们如何在层次聚类中使用树形图来确定聚类的数量。在下一节中,我们将实现层次聚类,这将帮助您理解我们在本文中学到的所有概念。

使用层次聚类解决批发商客户细分问题

是时候用Python弄脏我们的手了!

我们将解决批发商客户细分问题。数据托管在UCI机器学习存储库中。这个问题的目的是根据各种产品类别(如牛奶,杂货店,地区等)的年度支出来细分批发商的客户。

让我们先探索数据然后应用层次聚类来划分客户群。

首先导入所需的库:


 

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

%matplotlib inline

加载数据并查看前几行:


 

data = pd.read_csv('Wholesale customers data.csv')

data.head()

[译] 层次聚类的初学者指南(用 Python 实现)

有多种产品类别 - 生鲜,牛奶,杂货等。这些值代表每个客户购买每种产品的单位数量。我们的目标是从这些数据中创建可以将相似客户分组在一起的集群。当然,我们将使用层次聚类来解决这个问题。

但在应用层次聚类之前,我们必须对数据进行标准化,以使每个变量的衡量标准相同。为什么这很重要?因为如果标准不同,模型可能会变得偏向具有更高等级的变量,如生鲜或牛奶(参见上表)。

那么,让我们首先规范化数据并将所有变量带到相同的比例:


 

from sklearn.preprocessing import normalize

data_scaled = normalize(data)

data_scaled = pd.DataFrame(data_scaled, columns=data.columns)

data_scaled.head()

[译] 层次聚类的初学者指南(用 Python 实现)

我们可以看到所有变量的规模几乎都相似。首先绘制树图来帮助我们确定这个特定问题的聚类数量:


 

import scipy.cluster.hierarchy as shc

plt.figure(figsize=(10, 7))

plt.title("Dendrograms")

dend = shc.dendrogram(shc.linkage(data_scaled, method='ward'))

[译] 层次聚类的初学者指南(用 Python 实现)

x轴包含样本,y轴表示这些样本之间的距离。最大距离的垂直线是蓝线,因此我们可以确定阈值为6并切割树形图:


 

plt.figure(figsize=(10, 7))

plt.title("Dendrograms")

dend = shc.dendrogram(shc.linkage(data_scaled, method='ward'))

plt.axhline(y=6, color='r', linestyle='--')

[译] 层次聚类的初学者指南(用 Python 实现)

我们有两个簇,因为这条线在两点切割树状图。现在让我们为2个集群应用层次聚类:


 

from sklearn.cluster import AgglomerativeClustering

cluster = AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='ward')

cluster.fit_predict(data_scaled)

[译] 层次聚类的初学者指南(用 Python 实现)

我们可以在输出中看到0和1的值,因为我们定义了2个簇。0表示属于第一个簇的点,1表示第二个簇中的点。现在让我们想象两个集群:


 

plt.figure(figsize=(10, 7))

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

[译] 层次聚类的初学者指南(用 Python 实现)

真棒!我们可以清楚地看到这两个集群。这就是我们如何在Python中实现层次聚类。

结语

层次聚类是一种非常有用的观测分段方法。不必预先定义集群数量的优点使其比k-Means更具优势。

您对层次聚类有何看法?您是否觉得使用较少的计算资源创建集群有更好的方法?欢迎留言讨论!

原文链接 

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

原文项目Github

聚类简介和不同的聚类方法

https://www.analyticsvidhya.com/blog/2016/11/an-introduction-to-clustering-and-different-methods-of-clustering/?utm_source=blog&utm_medium=beginners-guide-hierarchical-clustering

封面图来源:pexels by Pok Rie

[译] 层次聚类的初学者指南(用 Python 实现)


以上所述就是小编给大家介绍的《[译] 层次聚类的初学者指南(用 Python 实现)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript & jQuery

JavaScript & jQuery

David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99

You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具