K-Means不断地取离种子点最近均值,将数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算。
算法流程:
(1)初始化选择K个点作为K个聚类样本中心
(2)迭代:计算每个样本点到中心点的距离,根据距离判断每个样本点所属类别;
各聚类根据属于自己这一类的样本点的均值更新聚类中心
(3)直到每个样本点所属类别不再变化
离群点问题:离群点将极大影响聚类中心的位置,通过寻找样本数很少的聚类在一定程度上找到离群点
算法后处理:对聚类进行进一步的分裂、合并或直接拆散或引进新的聚类中心等方法以达到更好的效果
代码实现:对788个点聚成7个类(使用Matlab)
(1)kMeans.m
<span style="font-size:12px;"><span style="font-size:14px;">clear; close all; clc;
load('788points.mat');
K = 7;
m = 788;
id = zeros(m, 1);
centroids = ...
[ X(50,1) X(70,2);
X(230,1) X(180,2);
X(360,1) X(280,2);
X(420,1) X(480,2);
X(570,1) X(400,2);
X(680,1) X(600,2);
X(750,1) X(700,2) ];
figure; hold on;
% 找到与当前聚类中心的距离最小的数组序号
for i=1:5
id = findClosestCentroids(K,X, centroids);
centroids = updateCentroids(X, id, K);
end
plotData(X, centroids,id, K);
hold off;
</span></span>
<span style="font-size:12px;"><span style="font-size:14px;">function id = findClosestCentroids(K,X, centroids)
id = zeros(size(X,1), 1);
for i=1:size(X)
min = norm((X(i,:) - centroids(1,:)),2);
id(i) = 1;
for j=2:K
if norm((X(i,:) - centroids(j,:)),2) < min
min = norm((X(i,:) - centroids(j,:)),2);
id(i) = j; end
end
end
end
</span></span>
<span style="font-size:12px;"><span style="font-size:14px;">function centroids = updateCentroids(X, idx, K)
[m n] = size(X);
centroids = zeros(K, n);
num = zeros(K,1);
%求和
for i=1:m
centroids(idx(i),:) = centroids(idx(i),:) + X(i,:);
num(idx(i)) = num(idx(i)) + 1;end
%求平均值
for j=1:K
centroids(j,:) = centroids(j,:) / num(j); end
end
</span></span>
(4)plotData.m
<span style="font-size:12px;"><span style="font-size:14px;">function plotData(X, centroids, idx, K)
% 画数据点
palette = hsv(K + 1);
colors = palette(idx, :);
scatter(X(:,1), X(:,2), 15, colors);
% 标出聚类中心
plot(centroids(:,1), centroids(:,2), 'x', ...
'MarkerEdgeColor','k', ...
'MarkerSize', 10, 'LineWidth', 3);
end
</span></span>
最终聚类结果: