12 聚类分析

物以类聚,人以群分,在现实世界中存在着大量的分类问题,聚类分析是研究分类问题的一种多元统计方法,在生物学、经济学、人口学、生态学、电子商务等很多方面有着非常广泛的应用。

更多MATLAB数据分析视频请点击,或者在网易云课堂上搜索《MATLAB数据分析与统计》 http://study.163.com/course/courseMain.htm?courseId=1003615016

  聚类分析的目的是把分类对象按一定的规则分成若干类,这些类不是事先给定的,而是根据数据的特征确定的,对类的数目和类的结构不必做任何假定。同一类里面的这些对象在某种意义上倾向于彼此相似,而在不同类例的对象倾向于不相似。

 这里主要介绍K均值聚类和模糊C聚类

1.K均值聚类

 K均值聚类有称为快速聚类法,是由麦奎因在1967年提出来的一种聚类方法,其基本步骤为:

 第一:选择k个样品作为初始凝聚点(聚类种子),或者将所有样本分成k个初始类,然后将k个类的重心(均值)作为初始凝聚点。

 第二:对除凝聚点之外的所有样本逐个归类,将每个样品归入离他最近的凝聚点所在的类,该类的凝聚点更新为这一类目前的均值,直至所有样品都归了类。

 第三:重复步骤二,直至所有的样本都不能再分配为止。

 注意:K均值聚类的最终聚类结果在一定程度上依赖于初始聚类点或初始分类的选择

1.1 K均值聚类的MATLAB函数

 与K均值聚类法相关函数有:kmeans和silhouette

 (1)kmeans函数

  kmeans函数用来做K均值聚类,将n个点(或观测)分为k类。聚类过程是动态的,通过迭代使得每个点与所属类重心距离的和达到最小。默认情况下,kmeans采用平方欧式聚类。调用格式如下:

 <1>IDX=kmeans(X,k)

  将n个点(或观测)分为k类,输入参数X为nxp的矩阵,矩阵的每一行对应一个点,每一列对应一个变量。输出参数IDX是一个nx1的向量,其元素为每个点所属类的类序号。

 <2>[IDX,C]=kmeans(X,k)

  返回k个类的重心坐标矩阵C,C是一个kxp的矩阵,第i行元素为第i类的类重心坐标。

<3>[IDX,C,sumd]=kmeans(X,k)

 返回类内距离(即类内各点与类重心距离之和)向量sumd,sumd是一个1xk的向量,第i个元素为第i类的类内距离之和。

<4>[IDX,C,sumd,D]=kmeans(X,k)

 返回每个点与每个类重心之间的距离矩阵D,D是一个nxk的矩阵,第i行第j列的元素是第i个点与第j类的重心之间的距离

<5>[.......]=kmeans(...,param1,val1,param2,val2,....)

 允许用户设置更多的参数及参数值,用来控制kmeans函数所用的迭代算法。param1,param2,...,为参数名,val1,val2,...,为相应的参数值,可用的参数名与参数值如下表:

参数名

参数值

说明

‘distance’

‘sqEuclidean’

平方欧式距离(默认情况)

‘cityblock’

绝对值距离

‘cosine’

把每个点作为一个向量,两点距离为1减去两个向量夹角余弦

‘correlation’

把每个点作为一个数值序列,两点间距离为1减去两个数值序列的相关系数

‘Hamming’

即不一致字节所占的百分比,仅适用于二进制数据

‘emptyaction’

‘error’

把空类作为错误对待(默认情况)

‘drop’

去除空类,输出参数C和D中相应值用NaN表示

‘singleton’

生成一个只包含最远点的新类

‘onlinephase’

‘on’

执行在线更新(默认情况)

‘off’

不执行在线更新

‘options’

由statest函数创建的结构体变量

用来设置迭代算法的相关选项

‘replicates’

正整数

重复聚类的次数

‘start’

‘sample’

随机选择k个观测点作为初始凝聚点

‘uniform’

在观测值矩阵X中随机并均匀地选择k个观测点作为初始凝聚点

‘cluster’

从X中随机选择10%个子样本,进行聚类运算,确定凝聚点。

‘Matrix’

若为kxp的矩阵,用来设定k个初始聚类点。若为kxpxm的3维数组,则重复进行m次聚类,每次聚类通过相应页上的二维数组设定k个初始凝聚点


(2)silhouette函数

 silhouette函数用来根据聚类的结果绘制轮廓,从轮廓中可以看出那个点的分类是否合理。轮廓图上第i个点的轮廓值定义为:

  S(i)=min(b)-a/max(a,min(b))

 其中,a是第i个点与同类的其他点之间的平均距离;b为一个向量,其元素是第i个点与不同类的类内各点之间的平均距离。

 轮廓值S(i)的取值范围为[-1,1],S(i)的值越大,说明第i个点的分类越合理,当S(i)<0时,说明第i个点的分类不合理,还有比目前分类更合理的分类。

 silhouette函数的调用格式如下:

 <1>slihouette(X,clust)

   更加样本矩阵X和聚类聚过clust绘制轮廓图。输入参数X是一个nxp的矩阵,矩阵的每一行对应一个观测值,每一列对应一个变量。clust是聚类的结果,可以是由每个观测所属的类序号构成的数值向量,也可以是由类名称构成的字符矩阵或字符串元胞数组。

<2> s=silhouette(X,clust)

   返回轮廓值向量s,他是以nx1的向量,其元素为相应点的轮廓值。此时不绘制轮廓。

<3>[s,h]=slihouette(X,clust)

 绘制轮廓图,并返回轮廓值向量s和图形句柄h。

<4>[......]=silhouette(X,clust,metric)

 指定距离计算的方法,绘制轮廓图。输入参数metric为字符串或距离矩阵,用来指定距离计算的方法或距离矩阵。silhouette函数支持的各种距离如下表:

 

metric参数取值

说明

‘Euclidean’

欧式距离

‘sqEuclidean’

平方欧式距离(默认情况)

‘cityblock’

绝对值距离

‘cosine’

把每个点作为一个向量,两点距离为1减去两个向量夹角余弦

‘correlation’

把每个点作为一个数值序列,两点间距离为1减去两个数值序列的相关系数

‘Hamming’

汉明距离

‘Jaccard’

不一致的非零坐标所占的百分比

Vector

上三角形式的距离矩阵对应的距离向量


<5>[....]=silhouette(X,clust,distfun,p1,p2,.....)

 接受函数句柄作为第三个参数即distfun,用来自定义距离计算的方法。


1.2 K均值距离的示例

 下表中列出了46个国家和地区3年(1990,2000,2006)的婴儿死亡率和出生时预期寿命数据,根据这些数据,利用K均值聚类法,对各个国家和地区进行聚类分析


[X, textdata] = xlsread('婴儿.xls');

%isnan函数的作用是如果x中有非数(NaNs,比如0/0),则取1,否则取0,
%这样isnan(x)得到的就是只含0和1的向量(或矩阵),
%这里我取A = isnan(x),则row=~any(isnan(x),2)可以写成row=~any(A,2),
%any(A, 2)表示对A的行向量判断,如果有非零数,则取1,否则取0;“~”表示逻辑非操作。
%最终,返回一个逻辑值,非缺失观察对应元素1,缺失观察对应元素0
row = ~any(isnan(X), 2);
X = X(row, :); %剔除掉了缺失数据,提取非缺失数据
countryname = textdata(3:end,1); %提取国家或地区名称
countryname = countryname(row);  %剔除缺失数据所对应的国家名称或地区名称

%将剔除缺失数据后的数据标准化
%数据标准化,即减去均值,然后除以标准差
X = zscore(X);  

%K均值聚类分析,分3类,也可以人为指定初始凝聚点
idx=kmeans(X,3);

% 绘制轮廓图 ,并返回轮廓值向量S和图形句柄H
[S, H] = silhouette(X,idx);

%查看聚类结果
countryname(idx == 1)  %查看第1类所包含的国家或地区
countryname(idx == 2)  %查看第2类所包含的国家和地区
countryname(idx == 3)  %查看第3类所包含的国家和地区


ans =

    ' 文    莱'
    ' 以 色 列'
    ' 日    本'
    ' 韩    国'
    ' 马来西亚'
    ' 新 加 坡'
    ' 斯里兰卡'
    ' 美    国'
    ' 阿 根 廷'
    ' 委内瑞拉'
    ' 捷    克'
    ' 法    国'
    ' 德    国'
    ' 意 大 利'
    ' 荷    兰'
    ' 波    兰'
    ' 西 班 牙'
    ' 英    国'
    ' 澳大利亚'
    ' 新 西 兰'


ans =

    ' 孟加拉国'
    ' 柬 埔 寨'
    ' 印    度'
    ' 老    挝'
    ' 缅    甸'
    ' 巴基斯坦'
    ' 尼日利亚'
    ' 南    非'


ans =

    ' 中    国'
    ' 印度尼西亚'
    ' 伊    朗'
    ' 哈萨克斯坦'
    ' 朝    鲜 '
    ' 蒙    古'
    ' 菲 律 宾'
    ' 泰    国'
    ' 越    南'
    ' 埃    及'
    ' 墨 西 哥'
    ' 巴    西'
    ' 俄罗斯联邦'
    ' 土 耳 其'
    ' 乌 克 兰'

以上给出了分为3类时的聚类结果,每一类中所包含的观测一目了然,非常直观。



2.模糊C均值聚类法

2.1模糊C均值聚类法

 很多分类问题中,分类对象之间没有明确的界限,往往具有这个类的特点,也有另一个类的特点。例如高与矮没有明确的界限,多高的人才是高人,可能每个人都有自己的判断。这类的问题,如果用传统的聚类方法(K均值聚类或系统聚类法)进行分类,把每个待分类的对象严格地划分到某个类中,这也存在一定的不合理性。这就需要使用模糊聚类进行分析。

 模糊聚类就是将n个样品划分为 c 类,记V={v1,v2,.....,vc}为 c 个类的聚类中心,在模糊划分中,每一个样品不是严格的划分为某一类,而是以一定的隶属度属于某一类,根据隶属度来确定样品的归属。

2.2 模糊C均值聚类法的MATLAB函数

 MATLAB模糊逻辑工具箱中提供了模糊C均值聚类的函数:fcm函数,它的调用格式如下:

 [center,U,obj_fcn]=fcm(data,cluster_n)

 [center,U,obj_fcn]=fcm(data,cluster_n,options)

 输入参数data是用于聚类的数据集,它是一个矩阵,每行对应一个样品(或观测),每列对应一个变量。cluster_n是一个正整数,表示类的个数。options是一个包含4个元素的向量,用来设置迭代的参数。options的第1个元素是隶属度的幂指数,其值应大于1,默认值为2;第2个参数是最大迭代次数,默认值为100;第3个参数是目标函数的终止容限,默认值为10^-5;第4个参数用来控制是否显示中间迭代过程,若取值为0,表示不显示中间迭代,否则显示。

 输出参数center是cluster_n个类重心坐标矩阵,它是cluster_n行,p列的矩阵。U是cluster_n行,n列的隶属度矩阵,它的第i行第k列元素uik表示第k个样品xk属于第i类的隶属度,可以根据U中每列元素的取值来判定每个样品的归属。obj_fcn是目标函数值向量,它的第i个元素表示第i步迭代的目标函数值,它所包含的元素的总数是实际迭代的总步数。

2.3 模糊C均值聚类示例

 下表中列出了我国31个省的12个月的月平均气温数据,根据这些观测数据,利用模糊C均值聚类法面对各地区进行聚类。


%读取数据,并进行标准化变换
[xdata,textdata] = xlsread('月平均气温.xls');
%提取元胞数组textdata第一列的第4行至最后一行,即城市名称数据
city = textdata(4:end,1);
%调用zscore函数将平均气温数据矩阵xdata进行标准话变换
X = zscore(xdata);

%进行模糊C均值聚类
%设置幂指数为3,最大迭代次数200,目标函数的终止容限为1e-6,不显示中间迭代过程
options = [3, 200, 1e-6, 0];
%调用fcm函数进行模糊C均值聚类,返回类中心坐标矩阵center
%隶属度矩阵U,目标函数值obj_fcn
[center,U,obj_fcn] = fcm(X,3,options)


center =

   -1.2112   -1.1743   -1.2768   -1.1717   -0.9853   -0.9953   -0.8856   -0.8888   -1.0991   -1.1692   -1.1928   -1.2039
   -0.0068    0.0092    0.1915    0.1204    0.2096    0.4829    0.1346    0.0285    0.0972    0.1299    0.0144   -0.0330
    0.7462    0.6674    0.6982    0.7619    0.7274    0.5940    0.9069    0.9482    0.8845    0.8567    0.8362    0.8068


U =

  Columns 1 through 12

    0.2075    0.2273    0.1149    0.4072    0.8180    0.7312    0.7023    0.6367    0.1059    0.1125    0.0866    0.1089
    0.5858    0.5614    0.7116    0.3973    0.1115    0.1628    0.1752    0.2106    0.3007    0.4368    0.2423    0.4463
    0.2067    0.2113    0.1734    0.1956    0.0705    0.1060    0.1226    0.1527    0.5934    0.4507    0.6711    0.4448

  Columns 13 through 24

    0.1085    0.0553    0.0823    0.0965    0.0967    0.0705    0.1555    0.1461    0.1903    0.1003    0.1296    0.2481
    0.2372    0.1516    0.7636    0.6941    0.2723    0.1988    0.2914    0.2933    0.3197    0.2330    0.5028    0.4730
    0.6543    0.7931    0.1541    0.2094    0.6310    0.7307    0.5531    0.5605    0.4900    0.6668    0.3676    0.2789

  Columns 25 through 31

    0.2735    0.4782    0.1075    0.7181    0.5477    0.4988    0.6758
    0.4002    0.2990    0.7092    0.1692    0.2574    0.3273    0.1986
    0.3263    0.2229    0.1833    0.1127    0.1949    0.1739    0.1256


obj_fcn =

   69.7755
   36.6628
   32.6049
   29.5032
   28.0235
   27.6362
   27.5577
   27.5379
   27.5316
   27.5292
   27.5282
   27.5278
   27.5276
   27.5275
   27.5275
   27.5275
   27.5274
   27.5274
   27.5274
   27.5274

返回的类中心坐标矩阵center是一个3x12的矩阵,每一行是一个雷的类中心坐标。隶属度矩阵U是一个3x31的矩阵,每一列是一个城市属于3个类的隶属度,例如U的第一列元素分别为0.2705,0.5858,和0.2067,表示北京属于第1类的隶属度为0.2075,属于第2类的隶属度为0.5858,属于第3类的隶属度为0.2067,由于北京属于第2类的隶属度比其他两个都大,可把北京归为第2类,其他城市的分类与之类似。返回的目标函数值obj_fcn是一个包含21个元素的列向量,说明求解过程中经过了21步迭代。


查看聚类结果

  由fcm函数返回的结果还不能很直观地看出每一个城市所属的类,下面通过查找每一个类中所包含的城市的序号(即查找隶属度矩阵U中的每一列中最大值的列标),来确定每个类中含有哪些城市

%查看聚类结果
%max函数返回每列的最大值,U(1,:)返回的是每列的第一个元素
id1 = find(U(1,:) == max(U));%如果列的最大值等于该列的第一个元素,则为第一类,返回的是该元素的列标,即为城市的序号
id2 = find(U(2,:) == max(U));%同上
id3 = find(U(3,:) == max(U));
city(id1)
city(id2)
city(id3)


ans =

    ' 太    原'
    ' 呼和浩特'
    ' 沈    阳'
    ' 长    春'
    ' 哈 尔 滨'
    ' 拉    萨'
    ' 兰    州'
    ' 西    宁'
    ' 银    川'
    ' 乌鲁木齐'


ans =

    ' 北    京'
    ' 天    津'
    ' 石 家 庄'
    ' 合    肥'
    ' 济    南'
    ' 郑    州'
    ' 温    州'
    ' 贵    阳'
    ' 昆    明'
    ' 西    安'


ans =

    ' 上    海'
    ' 南    京'
    ' 杭    州'
    ' 福    州'
    ' 南    昌'
    ' 武    汉'
    ' 长    沙'
    ' 广    州'
    ' 南    宁'
    ' 海    口'
    ' 重    庆'


注意:由于fcm函数通过生成随机数的方式确定隶属度矩阵的初值,因此调用fcm函数进行聚类时,每次聚类的结果可能会有细微差别(整体聚类结果相同,只是类的排序可能不同)。

更多MATLAB数据分析视频请点击,或者在网易云课堂上搜索《MATLAB数据分析与统计》 http://study.163.com/course/courseMain.htm?courseId=1003615016

原创文章 100 获赞 339 访问量 56万+

猜你喜欢

转载自blog.csdn.net/MATLAB_matlab/article/details/58620718