草庐IT

R实现KMeans聚类算法教程

梦想画家 2023-04-20 原文

本文和你一起学习无监督机器学习算法 ———— kmeans算法,并在R中给详细的实现示例和步骤。

什么是k-means聚类算法

聚类是从数据集中对观测值进行聚类的机器学习方法。它的目标是聚类相似观测值,不同类别之间差异较大。聚类是一种无监督学习方法,因为它仅尝试从数据集中发现结构,而不是预测应变量的值。

下面是一个市场营销中对客户分类的场景,通过下面客户信息:

  • 家庭收入
  • 住房面积
  • 户主职业
  • 据城区距离

我们利用这些信息进行聚类,可识别相似家庭,从而能够识别某类型家庭可能购买某种产品或对某种类型的广告反应更好。

最常用的聚类算法就是k-means聚类算法,下面我们介绍k-means算法并通过示例进行说明。

k-means聚类算法把数据集中每个观测值分为K个类别。每个分类中的观测值相当类似,K类之间彼此差异较大。实际应用中执行下列几步实现k-means聚类算法:

  1. 确定K值

首先确定把数据集分为几类。通常我们简单测试几个不同值K,然后分析结果,确定那个值更有现实意义。

  1. 将每个观察结果随机分配到一个初始簇中,从1到K。

  2. 执行以下步骤,直到集群分配停止变化。

  • 对于K个集群中的每一个,计算集群的质心。这仅仅是第k个簇中观测的p特征的向量。
  • 将每个观测值分配到质心最近的簇中。在这里最接近的是用欧氏距离来定义的。

下面通过示例展示R的实现过程。

R 实现kmeans聚类算法

加载包

首先加载两个包,包括kmeans算法的一些辅助函数。

library(factoextra)
library(cluster)

加载示例数据

对于本例我们将使用R中内置的usarrest数据集,该数据集包含1973年美国每个州每10万居民因谋杀、袭击和强奸而被捕的人数,以及每个州居住在城市地区的人口百分比(UrbanPop)。

#load data
df <- USArrests

#remove rows with missing values
df <- na.omit(df)

#scale each variable to have a mean of 0 and sd of 1
df <- scale(df)

#view first six rows of dataset
head(df)

#                Murder   Assault   UrbanPop         Rape
# Alabama    1.24256408 0.7828393 -0.5209066 -0.003416473
# Alaska     0.50786248 1.1068225 -1.2117642  2.484202941
# Arizona    0.07163341 1.4788032  0.9989801  1.042878388
# Arkansas   0.23234938 0.2308680 -1.0735927 -0.184916602
# California 0.27826823 1.2628144  1.7589234  2.067820292
# Colorado   0.02571456 0.3988593  0.8608085  1.864967207

上面代码首先加载USArrests数据集,删除缺失值,对数据值进行标准化。

寻找最佳聚类数量

执行kmeans聚类算法,我们可以使用内置包stat中的kmeans()函数,语法如下:

kmeans(data, centers, nstart)

  • data : 数据集名称
  • centers: 聚类数量,即选择k的值
  • nstart: 初始配置个数。因为不同的初始启动集合可能会导致不同的结果,所以建议使用几种不同的初始配置。k-means算法将找到导致簇内变异最小的初始配置。

既然在使用kmeans函数之前并不确定最优聚类数量,下面通过两个图来辅助我们决定:

  1. 聚类数量 vs. 总体平方和

首先使用 fviz_nbclust 函数创建一个图,展示聚类数量及总体平方和之间的关系:

fviz_nbclust(df, kmeans, method = "wss")

通常我们创建这类图形寻找某个K类对应的平方和值开始弯曲或趋于平缓的肘形。这通常是最理想的聚类数量。上图中显然在k = 4个时出现肘形

  1. 聚类数量 vs. 差距统计

另一个决定最佳聚类数量的是使用指标:差距统计。它用于比较不同k值聚类差距变化情况。使用cluster包中的clusGap()以及fviz_gap_stat()函数画图:

#calculate gap statistic based on number of clusters
gap_stat <- clusGap(df,
                    FUN = kmeans,
                    nstart = 25,
                    K.max = 10,
                    B = 50)

#plot number of clusters vs. gap statistic
fviz_gap_stat(gap_stat)

从上图可以看到k=4时,差距统计最大,这与前面图的结果一致。

使用最优k执行kmeans聚类

最后,我们执行kmeans函数,使用k=4作为最优值:

# 设置随机种子,让结果可以重现
set.seed(1)

# 调用kmeans聚类算法 k = 4
km <- kmeans(df, centers = 4, nstart = 25)

# 查看结果
km

# Show in New Window
# Clustering k = 1,2,..., K.max (= 10): .. done
# Bootstrapping, b = 1,2,..., B (= 50)  [one "." per sample]:
# .................................................. 50 
# R Console
# 
# 
# Show in New Window
# K-means clustering with 4 clusters of sizes 13, 13, 16, 8
# 
# Cluster means:
#       Murder    Assault   UrbanPop        Rape
# 1 -0.9615407 -1.1066010 -0.9301069 -0.96676331
# 2  0.6950701  1.0394414  0.7226370  1.27693964
# 3 -0.4894375 -0.3826001  0.5758298 -0.26165379
# 4  1.4118898  0.8743346 -0.8145211  0.01927104
# 
# Clustering vector:
#        Alabama         Alaska        Arizona       Arkansas     California       Colorado 
#              4              2              2              4              2              2 
#    Connecticut       Delaware        Florida        Georgia         Hawaii          Idaho 
#              3              3              2              4              3              1 
#       Illinois        Indiana           Iowa         Kansas       Kentucky      Louisiana 
#              2              3              1              3              1              4 
#          Maine       Maryland  Massachusetts       Michigan      Minnesota    Mississippi 
#              1              2              3              2              1              4 
#       Missouri        Montana       Nebraska         Nevada  New Hampshire     New Jersey 
#              2              1              1              2              1              3 
#     New Mexico       New York North Carolina   North Dakota           Ohio       Oklahoma 
#              2              2              4              1              3              3 
#         Oregon   Pennsylvania   Rhode Island South Carolina   South Dakota      Tennessee 
#              3              3              3              4              1              4 
#          Texas           Utah        Vermont       Virginia     Washington  West Virginia 
#              2              3              1              3              3              1 
#      Wisconsin        Wyoming 
#              1              3 
# 
# Within cluster sum of squares by cluster:
# [1] 11.952463 19.922437 16.212213  8.316061
#  (between_SS / total_SS =  71.2 %)
# 
# Available components:
# 
# [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
# [6] "betweenss"    "size"         "iter"         "ifault"     

从结果可见:

  • 16 州分在第一个类
  • 13 州分在第二个类
  • 13 州分在第三个类
  • 8 州分在第四个类

我们可以通过fviz_cluster()函数在二维空间中以散点图方式展示结果:

#plot results of final k-means model
fviz_cluster(km, data = df)

也可以使用aggregate()函数查看每个类中变量的均值:

#find means of each cluster
aggregate(USArrests, by=list(cluster=km$cluster), mean)

# cluster	  Murder   Assault	UrbanPop	    Rape
# 				
# 1	3.60000	  78.53846	52.07692	12.17692
# 2	10.81538 257.38462	76.00000	33.19231
# 3	5.65625	 138.87500	73.87500	18.78125
# 4	13.93750 243.62500	53.75000	21.41250

输出结果解释如下:

  • 在第一类中的州中平均每100,000人谋杀数为 3.6
  • 在第一类中的州中平均每100,000人袭击数为 78.5
  • 在第一类中的州中平均每100,000人城区居民率为 52.1%
  • 在第一类中的州中平均每100,000人强奸数为 3.6 12.2

最后我们把聚类结果附加到原始数据集中:

#add cluster assigment to original data
final_data <- cbind(USArrests, cluster = km$cluster)

#view final data
head(final_data)

# 	    Murder	Assault	UrbanPop  Rape	 cluster
# 				
# Alabama	    13.2	236	58	  21.2	 4
# Alaska	    10.0	263	48	  44.5	 2
# Arizona	     8.1	294	80	  31.0	 2
# Arkansas     8.8	190	50	  19.5	 4
# California   9.0	276	91	  40.6	 2
# Colorado     7.9	204	78	  38.7	 2

kmeans 算法的优缺点

优点:

  • 很快的算法
  • 能够处理大数据集

缺点:

  • 在执行算法之前需要指定聚类数量
  • 对异常值敏感

总结

本文我们讨论了kmeans算法的概念,并在R中给详细实现示例和步骤。

有关R实现KMeans聚类算法教程的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  3. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  6. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  7. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  8. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  9. hadoop安装之保姆级教程(二)之YARN的配置 - 2

    1.1.1 YARN的介绍 为克服Hadoop1.0中HDFS和MapReduce存在的各种问题⽽提出的,针对Hadoop1.0中的MapReduce在扩展性和多框架⽀持⽅⾯的不⾜,提出了全新的资源管理框架YARN. ApacheYARN(YetanotherResourceNegotiator的缩写)是Hadoop集群的资源管理系统,负责为计算程序提供服务器计算资源,相当于⼀个分布式的操作系统平台,⽽MapReduce等计算程序则相当于运⾏于操作系统之上的应⽤程序。 YARN被引⼊Hadoop2,最初是为了改善MapReduce的实现,但是因为具有⾜够的通⽤性,同样可以⽀持其他的分布式计算模

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐