目录
1 聚类简介
2 k-means算法流程
3 利用k-means 对数据进行聚类
4 利用K-means进行图像分割
5 小结
参考资料
1 聚类简介
在无监督学习中,训练样本的标记信息是未知的,我们的目标是通过对无标记训练样本的学习来解释数据的内在性质及规律,为了进一步的数据分析提供基础,此类学习应用最多的就是“聚类”(clustering)。
聚类(clustering) 就是视图将数据集中的样本划分为若干个互不相交的子集,每个子集称为一个簇(cluster)。通过这样的划分,每个簇可能对应于一些潜在的类别,如有一堆瓜,分为:有籽瓜和无籽瓜 或者 浅色瓜和深色瓜 或进口瓜和国产瓜 等分类。注意:这些概念对聚类算法而言是实现位置的,聚类过程是自动形成簇结构。
使用数学语言描述聚类为:假设有样本集 包含 个无标记样本,每个样本 是一个维的特征向量,则聚类算法需要将样本集 划分为 各互不相交的簇 ,其中 且 。相应的,我们用 表示样本 的“簇标记”(cluster label),即 。于是,聚类的结果可用包含个元素的簇标记向量 表示。
当看完这个数学描述时,心中默念:啥啥啥,这写的是啥。
其实,聚类没有那么难,上面的数学描述看着挺吓人的,其实通过简单地例子来说明,就基本理解了。下面就介绍经典的聚类算法——k-means (k均值)。
k-means是最简单的聚类算法之一,应用十分广泛,k-means以距离作为相似性的评价指标,其基本思想是按照距离将样本聚成不同的簇,两个点的距离越近,其相似度就越大,以得到紧凑且独立的簇作为聚类目标。
2 k-means算法流程
下面是k-means的算法流程:
输入:样本集 ;
聚类簇数 ;
过程:
1:从中随机选择个样本作为初始均值向量
2:repeat
3: 令
4: for do
5: 计算样本 与个均值向量 的距离: ;
6: 根据样本距离最近的均值向量确定 的簇标记: ;
7: 将样本 划入相应的簇: ;
8: end for9: for do
10: 计算新均值向量:
11: if then
12: 将当前均值向量 更新为
13: else
14: 保持当前均值向量不变
15: else if
16: end for
17:until 当前均值向量均未更新
输出:簇划分
直接看算法,一时半会很难理解,直接用实际数据一步步计算,更直观,下面用实际的数据进行实验。
3 利用k-means 对数据进行聚类
实验数据使用 周志华-机器学习 中的 西瓜数据集4.0 ,如表1所示:
编号 | 密度 | 含糖率 |
1 | 0.679 | 0.460 |
2 | 0.744 | 0.376 |
3 | 0.634 | 0.264 |
4 | 0.608 | 0.318 |
5 | 0.556 | 0.215 |
6 | 0.403 | 0.237 |
7 | 0.481 | 0.149 |
8 | 0.437 | 0.211 |
9 | 0.666 | 0.091 |
10 | 0.243 | 0.267 |
11 | 0.245 | 0.057 |
12 | 0.343 | 0.099 |
13 | 0.639 | 0.161 |
14 | 0.567 | 0.198 |
15 | 0.360 | 0.370 |
16 | 0.593 | 0.042 |
17 | 0.719 | 0.103 |
18 | 0.387 | 0.188 |
19 | 0.339 | 0.241 |
20 | 0.282 | 0.257 |
21 | 0.748 | 0.232 |
22 | 0.714 | 0.346 |
23 | 0.483 | 0.312 |
24 | 0.478 | 0.437 |
25 | 0.525 | 0.369 |
26 | 0.751 | 0.489 |
27 | 0.532 | 0.472 |
28 | 0.473 | 0.376 |
29 | 0.725 | 0.445 |
30 | 0.446 | 0.459 |
使用上面的数据集,假设现在需要聚类簇数 =3。
(1)首先随机选取三个样本 (编号为6,12,27对应的数据)作为初始均值向量,即:
=(0.403;0.237), =(0.343;0.099), =(0.532;0.472)
(2)将第一个样本 =(0.697;0.460)与当前的均值向量 计算他们之间的距离,距离结果为:0.369,0.506,0.166,因此第一个样本 被划入到簇 中。同样的,对数据集中的所有样本就进行计算,可得到当前簇划分为:
(3)从 中分别计算新的均值向量
=(0.473;0.214), =(0.394;0.066), =(0.623;0.388)
(4)重新进入(2)和(3),不断重复,知道当前的均值向量保持不变,即可停止。
分类的结果如下图所示:
下面是k-means聚类使用的Matlab代码
clear all;clc;tic;X=[0.679,0.460;0.744,0.376;0.634,0.264;0.608,0.318;0.556,0.215;0.403,0.237;0.481,0.149;0.437,0.211;0.666,0.091;0.243,0.267;0.245,0.057;0.343,0.099;0.639,0.161;0.567,0.198;0.360,0.370;0.593,0.042;0.719,0.103;0.387,0.188;0.339,0.241;0.282,0.257;0.748,0.232;0.714,0.346;0.483,0.312;0.478,0.437;0.525,0.369;0.751,0.489;0.532,0.472;0.473,0.376;0.725,0.445;0.446,0.459];k=3;
[Idx,Ctrs,SumD,D]=kmeans(X,k);%画出聚类为1的点。
%X(Idx==1,1),为第一类的样本的第一个坐标;
%X(Idx==1,2)为第二类的样本的第二个坐标
plot(X(Idx==1,1),X(Idx==1,2),'r.','MarkerSize',14)
hold on
plot(X(Idx==2,1),X(Idx==2,2),'b.','MarkerSize',14)
hold on
plot(X(Idx==3,1),X(Idx==3,2),'g.','MarkerSize',14)%绘出聚类中心点,kx表示是圆形
plot(Ctrs(:,1),Ctrs(:,2),'kx','MarkerSize',14,'LineWidth',4)
plot(Ctrs(:,1),Ctrs(:,2),'kx','MarkerSize',14,'LineWidth',4)
plot(Ctrs(:,1),Ctrs(:,2),'kx','MarkerSize',14,'LineWidth',4)legend('Cluster 1','Cluster 2','Cluster 3','Centroids','Location','NW')toc;
下面简单介绍Matlab 中 kmeans 函数如何使用:
kmeans 函数使用方法:
Idx=kmeans(X,K)
[Idx,C]=kmeans(X,K)
[Idx,C,sumD]=kmeans(X,K)
[Idx,C,sumD,D]=kmeans(X,K)
[…]=kmeans(…,’Name1’,Value1,’Name2’,Value2,…)
函数中,输入和输出参数的介绍:
X:数据为NP维度的矩阵;
K:表示将X划分为几类,为整数;
Idx:N1的向量,存储的是每个点的聚类标号;
C:KP的矩阵,存储的是K个聚类质心位置;
sumD:1K的和向量,存储的是类间所有点与该类质心点距离之和;
D:NK的矩阵,存储的是每个点与所有质心的距离;
[…]=kmeans(…,’Name1’,Value1,’Name2’,Value2,…);
这个用法可以查看 Matlab kmeans 帮助文档,这里简单介绍一下:Distance (距离测度) 和 Start (初始质心位置选择方法)
主要可以设置为如下:
1)‘Distance’:(距离测度),value如下:
‘sqEuclidean’ :欧式距离(默认时,采用此距离方式);
‘cityblock’ :绝度误差和,又称:L1;
‘cosine’ :针对向量;
‘correlation’ :针对有时序关系的值;
‘Hamming’ :只针对二进制数据;
Example: 'Distance','cityblock'
2) ‘Start’:初始质心位置选择方法,value如下:
‘sample’:从X中随机选取K个质心点;
‘uniform’: 根据X的分布范围均匀的随机生成K个质心;
‘cluster’: 初始聚类阶段随机选择10%的X的子样本(此方法初始使用’sample’方法;
Example: 'start','sample'
还有其他的参数设置,可以参见Matlab kmeans 帮助文档 。
4 利用K-means进行图像分割
下面是利用K-means进行图像分割的Matlab 代码:
clear all;clc;tic;C_Segments=2;%聚类的个数img_original = imread('lena.tiff');%读入图像
figure,imshow(img_original),title('原始图像'); %显示原图像
img_gray=rgb2gray(img_original);
figure,imshow(img_gray),title('原始灰度图像');% 获取图像的长宽
[m,n]=size(img_gray);% 灰度阈值计算
T=graythresh(img_gray);
img_bw=im2bw(img_gray,T);
figure,imshow(img_bw),title('原始二值图像');% 将图像进行RGB——3通道分解
R = reshape(img_original(:, :, 1), m*n, 1); % 将R分量各转为kmeans使用的数据格式m*n=512*512=262144行
G = reshape(img_original(:, :, 2), m*n, 1); % 将G分量各转为kmeans使用的数据格式m*n=512*512=262144行
B = reshape(img_original(:, :, 3), m*n, 1); % 将B分量各转为kmeans使用的数据格式m*n=512*512=262144行
dat = [R,G,B]; % r g b分量组成样本的特征,每个样本有三个属性值,共width*height个样本()
cRGB = kmeans(double(dat), C_Segments,'Distance','city', 'emptyaction','singleton','start','sample'); % 使用聚类算法分为2类rRGB = reshape(cRGB, m, n); % 反向转化为图片形式
figure, imshow(label2rgb(rRGB)),title('RGB通道分割结果'); % 显示分割结果% 将图像进行单一通道灰度分解
GraySeg= reshape(img_gray(:, :), m*n, 1);
cGray=kmeans(double(GraySeg), C_Segments);
rGray= reshape(cGray, m, n); % 反向转化为图片形式
figure, imshow(label2rgb(rGray)),title('灰度图分割结果'); % 显示分割结果toc;
分类结果如下图所示:
5 小结
k-means聚类算法的实现过程大致表示如下:
(1) 随机选取个初始聚类中心;
(2) 计算每个样本到各聚类中心的距离,将每个样本归到其距离最近的聚类中心;
(3) 对每个簇,以所有样本的均值作为该簇新的聚类中心;
(4) 重复第(2)~(3)步,直到聚类中心不再变化或达到设定的迭代次数。
参考资料
[1] https://blog.csdn.net/mrharvey/article/details/18085163
[2] https://blog.csdn.net/jteng/article/details/48811881
[3] https://blog.csdn.net/google19890102/article/details/52911835
[4] https://blog.csdn.net/mingtian715/article/details/51534165
[5] https://blog.csdn.net/a493823882/article/details/79282425
[6] Matlab kmeans 帮助文档
[7] 周志华 著. 机器学习, 北京: 清华大学出版社, 2016年1月.
[8] 机器学习(西瓜书). 公式推导解析