聚类是指事先不知道样本的类别,而利用样本的先验知识来构造“分类器”,是一种无监督学习。常用的聚类算法有分裂聚类法和动态聚类法等。
C均值聚类是一种动态聚类方法,概要为:第一步,选定某种距离作为样本间的相似性度量;第二步,确定评价聚类结果的准则函数;第三步,给出某种初始分类,用迭代法找出使准则函数取极值的最好聚类结果。
设待聚类的模式特征矢量集为,聚类数目C是事先设定的。算法的思想为取定C个类别和选取C个初始聚类中心,按最小距离原则将各模式分配到C类中的某一类,之后不断地计算聚类中心、调整各模式类别,最终使各模式到其聚类团类别中心的距离平方之和最小。算法步骤如下:
1) 任选C个模式特征矢量作为初始聚类中心:,令k=0。
2) 将待聚类的模式特征矢量集中的模式逐个按最小距离原则分划给c个类团中的某一类,即
:如果则
,
式中表示
和
的中心
的距离,上角标表示迭代次数。于是产生新聚类
。
3) 计算重新分类后的各类心
式中为聚类团
中所含模式的个数。
4) 如果,则结束,否则k=k+1,转至2。
function [idx, C, innerSumD, outerSumD] = cmeans(X, k, PlotOrNot)
%=======================================================
%function [idx, C, innerSumD, outerSumD] = cmeans(X, k, PlotOrNot)
%C均值聚类
%input: X:Original Data(n*l,n:variables, l:observation)
% k:number of clusters in the data(positive integer)
% PlotOrNot: true plot figures of cluster, false not plot
%output: idx:cluster indices(row vector)
% C:cluster centroid locations
% innerSumD:within-cluster sums of point-to-centroid distances
% outerSumD:sum distances between cluster
%Envirment:MATLABR2018b
%=======================================================
%% 1. 初始化类中心
[n, l] = size(X);
idx = ones(1, l);
idx(2) = 2;
m = zeros(n, k);
DrawColor = rand(k, 3);
iterations = 0; % 迭代次数
ind = randperm(l);
for i = 1 : k
m(:, i) = X(:, ind(i));
end
%% 2.使用Cmeans算法进行迭代聚类
idx1 = zeros(1, l);
tempD = zeros(k, l);
while sum(idx1 == idx) ~= l
iterations = iterations + 1;
innerSumD(iterations) = 0;
outerSumD(iterations) = sum(sqrt((sum((m - mean(m, 2)) .^ 2))), 2);
if PlotOrNot
figure();
title(sprintf('第%d次聚类结果', iterations));
hold on;
end
for i = 1 : k
innerSumD(iterations) = innerSumD(iterations) + ...
sum(sqrt(sum((X(:, idx == i) - m(:, i)) .^ 2)), 2) / l;
if PlotOrNot
scatter(X(1, find(idx == i)), X(2, find(idx == i)), ...
'MarkerFaceColor', DrawColor(i, :), 'MarkerEdgeColor', DrawColor(i, :));
end
end
if PlotOrNot
f = getframe;
imwrite(f.cdata, sprintf('第%d次聚类结果.png', iterations));
end
for i = 1 : k
tempD(i, 1: l) = sqrt(sum((X - m(:, i)) .^ 2, 1));
end
idx1 = idx;
[~, idx] = min(tempD);
for i = 1 : k
m(:, i) = mean(X(:, find(idx == i)), 2);
end
end
C = m;
if PlotOrNot
figure(), hold on;
plot(innerSumD, 'r-', 'LineWidth', 3);
plot(outerSumD, 'b--', 'LineWidth', 3);
plot(outerSumD ./ innerSumD, 'g-.', 'LineWidth', 3);
legend('聚类团内距离和', '聚类团间距离和', '聚类团间距离和/聚类团内距离和');
title('聚类准则示意图');
f = getframe;
imwrite(f.cdata, '聚类准则示意图.png');
end
end