python原理及代码_原理+代码|详解层次聚类及Python实现

前言

聚类分析是研究分类问题的分析方法,是洞察用户偏好和做用户画像的利器之一。聚类分析的方法非常多,能够理解经典又最基础的聚类方法 —— 层次聚类法(系统聚类) 的基本原理并将代码用于实际的业务案例是本文的目标,同时这也会为理解后续与聚类相关的推文如 K-Means 等打下基础是。

本文将详细介绍如何 利用 Python 实现基于层次聚类的客户分群,主要分为两个部分:层次聚类详细原理介绍

Python 代码实战讲解

原理部分

原理介绍

既然它们能被看成是一类的,所以要么它们距离近,要么它们或多或少有共同的特征。拿到数据集后,直接根据特征或指标来将样本分类的做法其实更适合业务能力比较强的人或有了十分明确的指标如男女各一类等硬性要求,所以本文以样本之间的距离为聚类指标。为了能够更好地深入浅出,我们调整了一下学习顺序,将小部分数学公式往后放,先从聚类结果的显示与分析入手。

下面是有关层次聚类的几个常见问题。

1、为什么都说层次树是层次聚类法独有的聚类结果图?

因为树形图的横坐标会将每一个样本都标出来,并展示聚类的过程。几十个样本时候层次树就已经 “无法” 查看了,更何况成百上千的数据样本。

6448c90ea8e0495ebc54010cf8918be6.png

2、层次树是怎么建立的?建立的基本步骤?

其实层次树的建立过程表示的就是聚类的过程,只不过通过层次树我们可以看出类之间的层次关系(这一类与那一类相差多远),同时还可以通过层次树决定最佳的聚类个数和看出聚类方式(聚类顺序的先后)

基本步骤比较简洁,只要短短的 3 步:计算每两个观测之间的距离

将最近的两个观测聚为一类,将其看作一个整体计算与其它观测(类)之间的距离

一直重复上述过程,直至所有的观测被聚为一类

建立层次树的三个步骤虽然简洁,但其实也有令人迷惑的地方,所以为了让各位更好的从整体上去理解聚类过程而不是圄于细节,这里先直接放一个聚类过程图和对应的层次树

39e9fc4b0c18793033a2deab38abc5c0.png

3、怎么从层次树中看出聚类过程?

这一个简短的问题中其实暗含不少门道,第一:**当两个点被分为一类时,是从横坐标出发向上延伸,后形成一条横杠;当两个类被分为一类时,是横杠中点向上延伸。**这第一点中,横杠的数量就表示当所有的点都被圈为一类的时候经过了多少次聚类。

82aaaf37c6b87ec9a4c5e16527f63eef.png

同样,横杠距离横坐标轴的高度也有玄机,毕竟每生成一个横杠就表示又有一次聚类了,所以我们可以通过横杠的高度判断聚类的顺序,结合上图右半部分的圆圈和数字标号也可以看出。

2be7979522c70fce94544c66d41008fd.png

所以聚类顺序便如下表:

聚类次数被聚为一类的点第1次1和3     →    1,3

第2次2和5     →     2,5

第3次2,5 和 4   →   2,5,4

第4次2,5,4 和 1,3   →   1,3,2,5,4

第5次1,3,2,5,4 和 6   →   1,3,2,5,4,6(所有点被聚为一类)

第二,整棵层次树是由一棵棵小树组成,每棵小树代表了一个类,小树的高度即是两个点或两个类之间的距离,所以两个点之间的距离越近,这棵树就越矮小。

e5531629904efbd55c2947dff981f663.png

下面这一段仔细阅读的话对理解点与点,类与类,点与类之间的距离是如何在层次树上体现很有帮助。先从最矮的高度只有 d1 小树说起,这就是类 1,3 中两个孤立的点 1 和 3 之间的距离;同理,d2 为类2,5 中点 2 和 5 之间的距离。

而至于 d3, d4, d5 这三个距离,他们并不像 d1 和 d2 那般表示的是一棵完整的树的高度,而更像是 “ 生长的枝干 ”,因为从第一点中的 “ 当两个类被分为一类时,是横杠中点向上延伸。” 可以看出 d3 是从类 2,5 横杠的中点往上延伸的,所以它表示会与另外的类聚成一起并形成一棵更大的树,图中即类 2,5 和点 4 被聚成一个新的类 2,5,4。

同理:d4 表示类 2,5,4 与类 1,3 聚成新类 1,3,2,5,4

d5 表示类 1,3,2,5,4 与点 6 聚成类 1,3,2,5,4,6

4、怎么从层次树中看出聚类情况?可以通过决定纵轴分界线可决定这些数据到底是分成多少类

0d92f1c9f62ed81b243d29ad8c421bad.png定好分界线后,只需要看距离这条线横杠和单独的竖线即可,上图中距离红线的横杠有两条(分别表示类1,2 和类2,5),单独的竖线也有两条,从横坐标轴 4 和 6 上各延伸出的一条。同理可用到下图

6021ffb06fa648ae8af87765bfa9e56b.png

为什么最好不要分成 3 组:13,254,6 呢?

因为树的高度表示两个点之间的距离,所以 4 到 类25 的距离只比到 类13 的距离要多如下图所示的一点点,所以硬是把 4 跟 25 分成一类就有点牵强了,正因为这种牵强的分类方式可能会让我们忽略 4 这个点单独的价值,所以我们不如直接将 4 看成单独的一类。

95aeb39c04c1d41e3d546e0862c3b2d5.png

推导与计算

接下来就是需要更加动脑的数学原理和公式部分了,我们需要知晓点与点,类与类,点与类这三种距离如何计算。

d3cee259b5501fcd94669d20e40696d8.png

最包罗万象的是明考斯基距离,因为 q 分别取 1 和 2 的时候就表示是绝对值距离和欧氏距离。点与点的距离很好求,我们一般用的都是欧氏距离,即初中学习的直角三角形三边关系,上图右上角点AC之间的距离(ab² + bc²) 后再开根号

而至于类与类之间的距离求法,其实经过了一个演变,篇幅原因本文只会一笔带过那些不常用的方法并将重心放在最常用和主流的方法上。

0260360c50a52b7d872011a27d780dfc.png

平均联接和重心法都已经比较少用了,现大多采用较少受异常值影响且不知数据分布的情况下依然能有较好表现的 Ward 法。

86cdbc06f534f4f853487a27f01e98b0.png

其实 Ward 法的公式与方差分析相似,都是通过组间距离来定夺点点/点类/类类间的距离,Ward 法许多详细的数学推导在网上有很多,这里我们直接展示最容易理解的一种:

431201606855b6e18df7e1728dcf65ad.png上图为已知的五个点和它们 x,y 轴坐标,SS 为 Ward 最小方差法的公式。

49abedf2a5b0b213aac300fa43f7217f.png

当两个点被聚为一类时,这一类的组间差异 SS 便为其中一点的某一坐标与另外的所有坐标加加减减的一系列操作(通俗解释,其实直接看上图的 SS 计算过程已经可以理解。)

了解 Ward 最小方差法的基本求解公式后,我们可以从最简单的聚类形式开始:5个点聚成4类。这意味着其中两个点会被聚在一起,剩下三个点各自为一类,所以总共会出现 C52 = 10 中情况,每种情况的组内 SS 分别如下表:

db76ecb2a463aa73735a981147588ad1.png同理,如果这 5 个点聚成 3/2/1 类的情况如下表:

892178da13f8daec36b026c258a34f5d.png需要注意的是:聚成两类后计算出 AB 这两个的利方差最小后,在后续聚成3类,2类的时候就直接把A和B两个看成是同一个个体了,所以不会再出现A和B分开的局面。

结合两个表,我们便可以得出如下结论:如果需要被聚成 4 类,AB为一类,剩下3个点各为一类最好(SS 最小)

如果需要被聚成 3 类,AB,DE为一类,剩下的 C 单独为一类最好

如果需要被聚成 2 类,AB,CDE各位一类

如果需要被聚成 1 类,对不起,我觉得没什么分析的必要

在进入代码实战前,我们简单总结一下原理部分提到的知识点:层次树的阅读

两个点之间的距离公式

Ward 法求类内的组间差异,用以决定聚出的类别个数

代码实战

在正式实战前,需要注意以下几点,首先原始数据通常需要经过处理才能用于分析:缺失值

异常值(极大或极小)

分类变量需要转化为哑变量(0/1数值)

分类变量类别不宜过多

其次由于变量的量纲的不一样引起计算距离的偏差,我们需要对数据进行标准化。同时不同的统计方法对数据有不同的要求:决策树和随机森林允许缺失值和异常值

聚类分析和回归模型则不支持缺失值

在处理数据时,也有两个问题值得关注,

1、聚类的时候,所有的 X 必须都是连续变量,为什么?

分类变量无法计算距离,如某个变量表示的是性别,男和女;教育程度为小学,初中,高中,大学,那该变量在各个个体之间的距离怎么计算?所以做聚类分析时尽可能用分类变量。

2、那这些分类变量的价值难道就无法利用了吗?

可以先根据其他的连续变量聚类,而后对分出来的类做描述性统计分析,这时候就可以用上分类变量的价值了。另外一种方法是可以在第一步就把分类变量也用上的聚类方法,不过需要结合实际业务。

以市场客户调研为例,属于 “ 客户的需求与态度 ” 这个分支,目的是依据调查问卷结果针对需求的数据分群,而调查分卷的问题中回答 “yes” 或者 “no” 类型的问题通常又会占一大部分,这时候我么可以通过合并多个问题回答的结果来将多个分类变量组合,生成一个连续变量,以电信客户的使用和需求情况为例:

497e764a2c5bc94a9a53c94c818dea27.png当然也还可以计算分类变量之间的 cos 相似度,即直接把分类变量设成距离。总之,分类变量在聚类当中是一定需要处理的。

现在终于到了正式的代码阶段,如果前面的原理都理解好了,代码的理解则可不费吹灰之力。这里我们使用一份公开的城市经济数据集,参数如下:AREA:城市名称

Gross:总体经济情况指数

Avg:平均经济情况指数import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

plt.rc('font', **{'family': 'Microsoft YaHei, SimHei'})  # 设置中文字体的支持

plt.rcParams['axes.unicode_minus'] = False

# 解决保存图像是负号'-'显示为方块的问题

df = pd.read_csv('城市经济.csv')

df

50ddcead8e5f72b45b77beb387cea609.png这些城市的指标分布如下波士顿矩阵图,篇幅原因绘图代码省略,后台回复关键字获取的源程序会一并提供。

b57e02ab2e6b37b5e7055da2a320cca1.pngsklearn 里面没有层次聚类的函数,所以从 scipy 中导入import scipy.cluster.hierarchy as sch

# 生成点与点之间的距离矩阵, 这里用的欧氏距离: euclidean

## X:根据什么来聚类,这里结合总体情况 Gross 与平均情况 Avg 两者

disMat = sch.distance.pdist(X=df[['Gross', 'Avg']], metric='euclidean')

# 进行层次聚类: 计算距离的方法使用 ward 法

Z = sch.linkage(disMat,method='ward')

下面是层次聚类可视化:层次树# 将层级聚类结果以树状图表示出来并保存

# 需要手动添加标签。

P = sch.dendrogram(Z, labels=df.AREA.tolist())

plt.savefig('聚类结果.png')

04fd30ef59ab940be4b4bc4ac5240d47.png

最后说一下,未来还会有 K-Means 等聚类方法的推文。作为深入浅出聚类方法的开端,我们只需知道层次聚类相比 K-Means 的好处是它不用事先指定我们需要聚成几类 (K-Means 算法代码中的参数 k 指定)

这样一来,我们只需要把计算全权交给程序,最终能得出一个比较精准的结果。但缺点是随之而来的计算复杂度的增加。

所以层次聚类更适合小样本;K-Means 更适合大样本,在数据挖掘中也更常见,本文分享就到这里,我们下期决策树见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java但中获取时间将时间转换成字符串格式(年月日格式)

一:直接上马拿走: package cn.wyj.one;import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date;/*** 测试时间对象和字符串之间的相互转化* DateFormat抽象类和SimpleDateFormat实现类的使用* author 86155**/public class Demo2…

一行代码就可以替换n个仓储文件

( 且放白鹿青崖间,须行即骑访名山 )终于还是要面对这个问题了,一直想着可以逃避它,自从18年就开始纠结这个问题,后来看了DDD,然后也收集了很多的设计思想,发现一个框架除了稳定性&am…

JAVA当中Calendar类打印日历表单

一:引言 代码当中注释很详尽,直接上码; 二:上码 package cn.wyj.one;import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date…

基于.NetCore3.1系列 —— 日志记录之日志配置揭秘

前言在项目的开发维护阶段,有时候我们关注的问题不仅仅在于功能的实现,甚至需要关注系统发布上线后遇到的问题能否及时的查找并解决。所以我们需要有一个好的解决方案来及时的定位错误的根源并做出正确及时的修复,这样才能不影响系统正常的运…

7-21 求前缀表达式的值 (25 分)(思路详解)

一:题目 算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如23*(7-4)8/4的前缀表达式是: 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。 输入格式: 输入在一行内给出不超过…

java当中递归打印目录树

一&#xff1a;上码 package cn.wyj.one;import java.io.File;public class Demo8_递归打印目录树 {public static void main(String[] args) {File f new File("C:/亚洲");printfile(f,0);}static void printfile(File f,int level){for( int i 0; i < level;…

今天你内卷了吗?

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份最近「内卷」这个词大火&#xff0c;朋友圈、知乎、腾讯新闻、B站视频&#xff0c;铺天盖地。大家的议论充满了愤懑、不安、失望和愤怒。那么&#xff0c;什么是内卷&#xff1f;内卷并不是一个新词&#xff…

python中的正则表达式re模块_python中的正则表达式(re模块)

特殊字符"."  &#xff1a; Matches any character except a newline.匹配任何字符 除了换行符"^"  :匹配字符的开头1 importre2 sre.findall(^c234,ac2324)3 s1re.findall(^ac,ac2324)4 print(s)5 print(s1)6 #输出&#xff1a;[]7 # [ac]"$&quo…

.NET Core + Spring Cloud:服务注册与发现

毫无疑问&#xff0c;微服务架构是目前的主流&#xff0c;在微服务架构下&#xff0c;服务治理、负载均衡、服务熔断、配置中心、API网关 等都是需要关注的问题&#xff0c;当然不是非要全部完善后才能进行微服务开发&#xff0c;在很多项目团队中&#xff0c;初期可能会将某个…

python语言中不用来定义函数的关键字_Python 语言中用来定义函数的关键字是

Python 语言中用来定义函数的关键字是答&#xff1a;def调查问卷采集是数据采集人员通过设计具有针对性的问卷,采用方式进行信息采集答&#xff1a;以上都是中国大学MOOC: 突出重点&#xff0c;必须以解决问题为目标。也就是说&#xff0c;重点内容的训练&#xff0c;必须实现预…

C++中getline()和cin()同时使用时的注意事项

一&#xff1a;问题 当用cin输入完后 然后再用getline()的话就会直接结束没办法在输入了 问题分析&#xff1a; cin只是在缓存区中&#xff0c;把字符读走&#xff0c;会剩余/n在缓存区中&#xff0c;但是getline对/n极度敏感&#xff0c;导致getline刚开始读入便遇到/n于是…

api接口返回动态的json格式?我太难了,尝试一下 linq to json

一&#xff1a;背景1. 讲故事前段时间和一家公司联调api接口的时候&#xff0c;发现一个奇葩的问题&#xff0c;它的api返回的json会动态改变&#xff0c;简化如下&#xff1a;{"Code":101,"Items":[{"OrderTitle":"订单1"}]}{"C…

mysql id 字段类型转换_mysql 数据类型转换

一、问题有一张如下图所示的表&#xff0c;需要我们查出 result 值大于 reference_high值的数据然后我们写了下面的SQL查询语句SELECT i.result,i.reference_high FROM report_item iLEFT JOIN report r ON r.idi.report_idWHERE r.org_id54 AND r.report_status1AND r.add_dat…

7-22 堆栈模拟队列 (25 分)(详解夹思路)

一&#xff1a;题目 设已知有两个堆栈S1和S2&#xff0c;请用这两个堆栈模拟出一个队列Q。 所谓用堆栈模拟队列&#xff0c;实际上就是通过调用堆栈的下列操作函数: int IsFull(Stack S)&#xff1a;判断堆栈S是否已满&#xff0c;返回1或0&#xff1b; int IsEmpty (Stack …

What is 测试金字塔?

【答疑解惑】| 作者 / Edison Zhou这是恰童鞋骚年的第271篇原创内容我的女朋友是一名测试工程师&#xff0c;但她之前却不知道测试金字塔的概念&#xff0c;为此我曾经在家里的白板上画了一个图一层一层给她讲解过。我和同事在给团队面试测试和开发岗位时&#xff0c;也会必问到…

Mysql编码教程_mysql编码设置教程 mysql编码要怎么设置呢

mysql的默认编码是拉丁&#xff0c;每次JSP制作网页用insert语句插入数据库时汉字都会显示成问号&#xff0c;安装mysql后&#xff0c;启动服务并登陆&#xff0c;使用show variables命令可查看mysql数据库的默认编码:由上图可见database和server的字符集使用了latin1编码方式&…

技术脱钩后软硬件磨合优化不失为一条出路

从宏观上看&#xff0c;这一论的制裁只是一连串组合拳的一次攻击&#xff0c;将来&#xff0c;东亚大国和西方技术脱钩是大趋势。在这种背景下&#xff0c;宜建立红色产业链。指导方针是不过度追求局部指标的先进性&#xff0c;而是追求技术自主性&#xff0c;并把握整体性能达…

7-23 还原二叉树 (25 分)(分析加详解)

一&#xff1a;题目&#xff1a; 给定一棵二叉树的先序遍历序列和中序遍历序列&#xff0c;要求计算该二叉树的高度。 输入格式: 输入首先给出正整数N&#xff08;≤50&#xff09;&#xff0c;为树中结点总数。下面两行先后给出先序和中序遍历序列&#xff0c;均是长度为N的…

dotNET:怎样处理程序中的异常(实战篇)?

在上篇 《dotNET&#xff1a;怎样处理程序中的异常&#xff08;理论篇&#xff09;》 中讲了一些程序中出现异常怎样处理的理论知识&#xff0c;本文将以代码的方式来进行实践。环境dotNET Core&#xff1a;3.1工具&#xff1a;Rider 2019.3.2系统&#xff1a;macOS 10.15.4创建…

在 MySQL 中使用码农很忙 IP 地址数据库

在下载到码农很忙 IP 地址数据库后&#xff0c;我们可以将其存储在 MySQL 数据库中&#xff0c;并在需要查询某个 IP 对应的位置数据时&#xff0c;通过 SQL 语句获取正确的结果。这是一种很便捷的使用方式&#xff0c;并且在增加了恰当的索引后&#xff0c;可以取得不错的搜索…