聚类是把一个数据集划分红多个子集的过程,每个子集称做一个簇(Cluster),聚类使得簇内的对象具备很高的类似性,但与其余簇中的对象很不类似,由聚类分析产生的簇的集合称做一个聚类。在相同的数据集上,不一样的聚类算法可能产生不一样的聚类。html
聚类分析用于洞察数据的分布,观察每一个簇的特征,进一步分析特定簇的特征。因为簇是数据对象的子集合,簇内的对象彼此类似,而与其余簇的对象不类似,所以,簇能够看做数据集的“隐性”分类,聚类分析可能会发现数据集的未知分组。算法
聚类经过观察学习,不须要提供每一个训练元素的隶属关系,属于无监督式学习(unspervised learning),无监督学习是指在没有标注的数据中寻找隐含的结构信息。数据的内部构造描绘了要分组的对象,而且决定了如何最佳地把数据对象分组。主要的聚类算法能够分为如下四类:ide
本文简单介绍最简单的划分聚类算法,划分聚类是指:给定一个n个对象的集合,划分方法构建数据的k个分组,其中,每一个分区表示一个簇,而且 k<= n,也就是说,把数据划分为k个组,使得每一个组至少包含一个对象,基本的划分方法采起互斥的簇划分,这使得每一个对象都仅属于一个簇。为了达到全局最优,基于划分的聚类须要穷举全部可能的划分,计算量极大,实际上,经常使用的划分方法都采用了启发式方法,例如k-均值(k-means)、k-中心点(k-medoids),渐进地提升聚类质量,逼近局部最优解,启发式聚类方法比较适合发现中小规模的球状簇。函数
k-均值(kmeans)是一种基于形心的计数,每个数据元素的类型是数值型,k-均值算法把簇的形心定义为簇内点的均值,k-均值算法的过程:性能
输入: k(簇的数目),D(包含n个数据的数据集)学习
输出: k个簇的集合idea
算法:spa
- 从D中任意选择k个对象做为初始簇中心;
- repeat
- 根据cu中对象的均值,把每一个对象分配到最类似的簇;
- 更新簇的均值,即从新计算每一个簇中对象的均值;
- until 簇均值再也不发生变化
不能保证k-均值方法收敛于全局最优解,但它经常终止于局部最优解,该算法的结果可能依赖于初始簇中心的随机选择。.net
k-均值方法不适用于非凸形的簇,或者大小差异很大的簇,此外,它对离群点敏感,由于少许的离群点可以对均值产生极大的影响,影响其余簇的分配。code
R语言中,stats包中的kmeans()函数用于实现k-均值聚类分析:
kmeans(x, centers, iter.max = 10, nstart = 1, algorithm = c("Hartigan-Wong", "Lloyd", "Forgy","MacQueen"), trace=FALSE)
参数注释:
函数返回的值:
k-中心点不使用簇内对象的均值做为参照点,而是挑选实际的数据对象p来表明簇,其他的每一个对象被分配到与其最为类似的对象表明p所在的簇中。一般状况下,使用围绕中心点划分(Partitioning Around Medoids,PAM)算法实现k-中心点聚类。
PAM算法的实现过程:
输入: k(簇的数目),D(包含n个数据的数据集)
输出: k个簇的集合
算法:
- 从D中随机选择k个对象做为初始的表明对象或种子;
- repeat
- 把每一个剩余的对象分配到最近的表明对象p所在的簇;
- 随机地选择一个非表明对象R
- 计算用R代替表明对象p的总代价S;
- if S<0 then 使用R代替p,造成新的k个表明对象的集合;
- until 表明对象再也不变化
当存在离群点时,k-中心点方法比k-均值法更鲁棒(所谓“鲁棒性”,是指控制系统在必定(结构,大小)的参数摄动下,维持某些性能的特性),这是由于中心点不像均值法那样容易受到离群点或其余极端值的影响。可是,当n和k的值较大时,k-中心点计算的开销变得至关大,远高于k-均值法。
R语言中,cluster包中的pam()函数用于实现k-中心点聚类分析:
pam(x, k, diss = inherits(x, "dist"),metric = c("euclidean", "manhattan"), medoids = NULL, stand = FALSE, ... )
参数注释:
函数返回的对象:
当咱们再数据集上试用一种聚类方法时,如何评估聚类的结果的好坏?通常来讲,聚类评估主要包括如下任务:
1,估计聚类趋势
聚类要求数据是非均匀分布的,霍普金斯统计量是一种空间统计量,用于检验空间分布的变量的空间随机性。
comato包中有一个Hopkins.index()函数,用于计算霍普金斯指数,若是数据分布是均匀的,则该值接近于0.5,若是数据分布是高度倾斜的,则该值接近于1。
library(comato)
Hopkins.index(data)
要使用Hopkins.index()评估数据的空间随机性,须要对数据进行无量纲化处理。
2,肯定最佳的簇数
一般状况下,使用肘方法(elbow)以肯定聚类的最佳的簇数,肘方法之因此是有效的,是基于如下观察:增长簇数有助于下降每一个簇的簇内方差之和,给定k>0,计算簇内方差和var(k),绘制var关于k的曲线,曲线的第一个(或最显著的)拐点暗示正确的簇数。
sjPlot包中sjc.elbow()函数实现了肘方法,能够用于肯定k-均值聚类的簇的数目:
library(sjPlot) sjc.elbow(data, steps = 15, show.diff = FALSE)
参数注释:
sjc.elbow()函数用于绘制k-均值聚类分析的肘值,该函数在指定的数据框计算k-均值聚类分析,产生两个图形:一个图形具备不一样的肘值,另外一个图形是链接y轴上的每一个“步”,即在相邻的肘值之间绘制连线,第二个图中曲线的拐点可能暗示“正确的”簇数。
绘制k均值聚类分析的肘部值。 该函数计算所提供的数据帧上的k均值聚类分析,并产生两个图:一个具备不一样的肘值,另外一个图绘制在y轴上的每一个“步”(即在肘值之间)之间的差别。 第二个图的增长可能代表肘部标准。
library(effects)
library(sjPlot)
library(ggplot2)
sjc.elbow(mtcars,show.diff = FALSE)
从肘值图中,能够看到曲线的拐点是3,还可使用NbClust包种的NbClust()函数,该函数提供了26个不一样的指标来帮助肯定簇的最终数目。
library(NbClust) nc <- NbClust(df,min.nc = 2,max.nc = 15,method = "kmeans") barplot(table(nc$Best.nc[1,]),xlab="Number of Clusters",ylab="Number of Criteria",main="number of Clusters Chosen by 26 Criteria")
从条形图种,能够看到支持簇数为3的指标(Criteria)的数量是最多的,所以,基本上能够肯定,k-均值聚类的簇数目是3。
3,测定聚类质量
如何比较不一样聚类算法产生的聚类?通常而言,根据是否有基准可用,把测定聚类质量的方法分为两类:外在方法和内在方法。
基准是一种理想的聚类,一般由专家构建。若是有可用的基准,那么能够把聚类和基准进行比较,这种方法叫作外在方法。若是没有基准可用,那么经过考虑簇的分离状况来评估簇的好坏,这种方法叫作内在方法。
(1)外在方法
当有基准可用时,使用BCubed 精度(precision)和召回率(recall)来评估聚类的质量。
BCubed根据基准,对给定数据集上聚类中每一个对象评估精度(precision)和召回率(recall)。一个对象的精度是指同一簇中有多少个其余对象与该对象同属于一个类别;一个对象的召回率反映有多少同一类别的对象被分配到相同的簇中。
(2)内在方法
当没有数据集的基准可用时,必须使用内在方法来评估聚类的质量。通常而言,内在方法经过考察簇的分离状况和簇的紧凑状况来评估聚类,一般的内在方法都使用数据集的对象之间的类似性度量来实现。
轮廓系数(silhouette coefficient)就是这种类似性度量,轮廓系数的值在-1和1之间,该值越接近于1,簇越紧凑,聚类越好。当轮廓系数接近1时,簇内紧凑,并远离其余簇。
若是轮廓系数sil 接近1,则说明样本聚类合理;若是轮廓系数sil 接近-1,则说明样本i更应该分类到另外的簇;若是轮廓系数sil 近似为0,则说明样本i在两个簇的边界上。全部样本的轮廓系数 sil的均值称为聚类结果的轮廓系数,是该聚类是否合理、有效的度量。
包fpc中实现了计算聚类后的一些评价指标,其中就包括了轮廓系数:avg.silwidth(平均的轮廓宽度)
library(fpc) result <- kmeans(data,k) stats <- cluster.stats(dist(data)^2, result$cluster) sli <- stats$avg.silwidth
包cluster中也包括计算轮廓系数的函数silhouette():
library (cluster) library (vegan) #pam dis <- vegdist(data) res <- pam(dis,3) sil <- silhouette (res$clustering,dis) #kmeans dis <- dist(data)^2 res <- kmeans(data,3) sil <- silhouette (res$cluster, dis)
有效的聚类分析是一个多步骤的过程,其中每一次决策均可能影响聚类结果的质量和有效性,咱们使用k-均值聚类来处理葡萄酒中13种化学成分的数据集wine,这个数据集能够经过rattle包得到,
install.packages("rattle") data(wine,package="rattle") head(wine) Type Alcohol Malic Ash Alcalinity Magnesium Phenols Flavanoids Nonflavanoids Proanthocyanins Color Hue Dilution Proline 1 1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065 2 1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050 3 1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185 4 1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480 5 1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735 6 1 14.20 1.76 2.45 15.2 112 3.27 3.39 0.34 1.97 6.75 1.05 2.85 1450
1,选择合适的变量
第一个变量Type是类型,能够忽略,其余13个变量是葡萄酒的13总化学成分,选择这13个变量进行聚类分析。因为变量值变化很大,因此须要在聚类以前对其进行标准化处理。
2,标准化数据
使用scale()函数对数据进行无量纲化处理,
df <- scale(wine[,-1])
3,评估聚类的趋势
变量df的变量值是无量纲的,能够直接使用函数Hopkins.index()计算数据的空间分布的随机性,得出的结果越接近于1,说明数据的空间分布高度倾斜,空间随机性越高。
install.packages("comato")
library(comato) Hopkins.index(df) [1] 0.7412846
4,肯定聚类的簇数
使用sjPlot包中的sjc.elbow()函数计算肘值,曲线的拐点出现3左右,这说明,使用k-均值法进行聚类分析时,能够设置的簇数大概是3。
install.packages("effects") install.packages("sjplot") library(effects) library(sjPlot) library(ggplot2) sjc.elbow(df,show.diff = FALSE)
从肘值图中,能够看到曲线的拐点是3,还可使用NbClust包种的NbClust()函数,该函数提供了26个不一样的指标来帮助肯定簇的最终数目。
install.packages("NbClust") library(NbClust) nc <- NbClust(df,min.nc = 2,max.nc = 15,method = "kmeans") barplot(table(nc$Best.nc[1,]),xlab="Number of Clusters",ylab="Number of Criteria",main="number of Clusters Chosen by 26 Criteria")
从条形图种,能够看到支持簇数为3的指标(Criteria)的数量是最多的,所以,基本上能够肯定,k-均值聚类的簇数目是3。
5,测定聚类的质量
使用轮廓系数测定聚类的质量,轮廓系数的值在-1和1之间,该值越接近于1,簇越紧凑,聚类越好。当轮廓系数接近1时,簇内紧凑,并远离其余簇。
install.packages("fpc")
library(fpc) for(k in 2:9){ result <- kmeans(df,k) stats <- cluster.stats(dist(df)^2, result$cluster) sli <- stats$avg.silwidth print(paste0(k,'-',sli)) }
当簇数目为3时,聚类的轮廓系数0.45是最好的。
[1] "2-0.425791262898175" [1] "3-0.450837233419168" [1] "4-0.35109709657011" [1] "5-0.378169006474844" [1] "6-0.292436629924875" [1] "7-0.317163857046711" [1] "8-0.229405778112672" [1] "9-0.291438101137107"
参考文档: