K-means算法及Matlab实现
文章目录
K-MEANS CLUSTERING
方法介绍
K-means 是经典的聚类算法,也是数据挖掘十大经典算法之一。聚类思想就是无监督学习中将较为相似的数据归为一类的,正所谓“物以类聚,人以群分”,大约就是这样,而 K- means 就是聚类算法中最为简洁,高效的一种,他是用于在无监督学习中,在一群未标注的数据中寻找聚类(culster)和聚类中心(cluster center)的方法。
- 核心思想:选定 K 个聚类中心, 通过算法不断迭代移动中心位置以极小化聚类集群内部的方差总和。
算法介绍
- 当我们给定了初始中心以后,K-means 算法交替进行两个步骤:
1、对每一个中心我们识别出比起别的任何聚类点离某个聚类点更近的子群。
2、计算出每个集群中的数据点的特征均值,这个均值向量就成为这个集群的新的中心。 重复迭代这两步,直到算法收敛。
K-means 优缺点
- 优点:
1、 计算时间短,收敛速度快。
2、需要调参的话就只要 K 一个参数。(iii) 容易解释。 - 缺点:
1、初始 K 值需要预先给定:而这个很大程度取决于经验,但是这个 K 值是否能正确选取,也决定了 K-means 能否有效率的正确分类。
2、K-means 相当依赖一开始选取的聚类中心,而开始的聚类中心是随机选取的也就是说有相当比例的只能取得局部最小值而无法取得全局最小值。
3、K-means 无法适用于所有的数据集类型。
4、对于过于离散的点和奇异点的聚类效果也不好。
CODE
MATLAB代码
主程序
%% input the data
A = load('testSet.txt');
%% 计算质心
centroids = kMeans(A, 4);
随机选取质心
%% 取得随机中心
function [ centroids ] = randCent( dataSet, k )
[m,n] = size(dataSet);%取得列数
centroids = zeros(k, n);
for j = 1:n
minJ = min(dataSet(:,j));
rangeJ = max(dataSet(:,j))-min(dataSet(:,j));
centroids(:,j) = minJ+rand(k,1)*rangeJ;%产生区间上的随机数
end
end
计算相似性
function [ dist ] = distence( vecA, vecB )
dist = (vecA-vecB)*(vecA-vecB)';%这里取欧式距离的平方
end
k-Means的主程序
[plain] view plain copy
%% kMeans的核心程序,不断迭代求解聚类中心
function [ centroids ] = kMeans( dataSet, k )
[m,n] = size(dataSet);
%初始化聚类中心
centroids = randCent(dataSet, k);
subCenter = zeros(m,2); %做一个m*2的矩阵,第一列存储类别,第二列存储距离
change = 1;%判断是否改变
while change == 1
change = 0;
%对每一组数据计算距离
for i = 1:m
minDist = inf;
minIndex = 0;
for j = 1:k
dist= distence(dataSet(i,:), centroids(j,:));
if dist < minDist
minDist = dist;
minIndex = j;
end
end
if subCenter(i,1) ~= minIndex
change = 1;
subCenter(i,:)=[minIndex, minDist];
end
end
%对k类重新就算聚类中心
for j = 1:k
sum = zeros(1,n);
r = 0;%数量
for i = 1:m
if subCenter(i,1) == j
sum = sum + dataSet(i,:);
r = r+1;
end
end
centroids(j,:) = sum./r;
end
end
%% 完成作图
hold on
for i = 1:m
switch subCenter(i,1)
case 1
plot(dataSet(i,1), dataSet(i,2), '.b');
case 2
plot(dataSet(i,1), dataSet(i,2), '.g');
case 3
plot(dataSet(i,1), dataSet(i,2), '.r');
otherwise
plot(dataSet(i,1), dataSet(i,2), '.c');
end
end
plot(centroids(:,1),centroids(:,2),'+k');
end
实验验证
取一散点数据集,包含 90 组二维数据,如图 1 所示:
通过观察我们选取 K=4,即希望将数据分为四类,目测观察我们可知数据大致上是左上, 左下,右上,右下四类,运行算法后我们得到图 2。
图 1.2. 利用 K-means 得到的正确的聚类结果 |
---|
图 2 基本满足我们原本对于数据聚类的预期。但是是否每次都是得到图 2 这样的表示呢?
事实上并不是的,对于其中的某些奇异点在大部分聚类中,摇摆不定的状态。当我连续出图 20-50 张的时候我们发现了有一定比例会得到类似于 图 3 右上角的分类状态(试验次数较小并 不能完全确定正确率,当实验 50 次的时候错误率大约在 10—15%),也就是即使我们选对了 K 的值,当初始的点没有随机到正确的集群的时候,分类也会出现偏差。
同时我们选取了不同的 K 值,3,4,5,6 在的得到的实验结果中我们选取图 3 为例,可 以观察到不同 K 值对分类是否正确有着决定性作用的。