KMeans算法
1. \(k\)均值算法原理
给定一个数据集\(D=\{x_1,x_2,...,x_m\}\),\(k\)均值算法针对聚类所得划分\(C=\{C_1,C_2,...,C_K\}\)最小化平方误差
\[ E = \sum_{i=1}^{k}\sum_{x\in{C_i}}
\begin{Vmatrix}
{x-\mu_i}
\end{Vmatrix}_2^2
\]
其中,\(\mu_i=\frac{1}{\mid{C_i}\mid}\sum_{x\in{C_i}}x\)是簇\(C_i\)的均值向量。刻画了簇内样本围绕簇均值向量的紧密程度,\(E\)值越小则簇内样本相似度越高。
2. 算法伪代码
- 输入数据集\(D\);
- 确定聚类簇数\(k\);
- 从数据集中选择\(k\)个样本作为初始聚类中心;
- 根据距离最小原则,将每个数据分配个相应的簇心;
- 计算平方误差
- 更新每个簇的簇心;
- 停止条件:平方误差不再变化. 否则,重复4,5,6.
3. 算法代码实现
clc
clear
%% input data
load two_cluster.txt
%% 数据预处理
target = two_cluster(:, 1);
data = two_cluster(:, [2,3]);
%% 原始数据分布可视化
figure
scatter(data(:,1), data(:,2));
%% parameters setting
k = 2; % 类别数目
N_iter = 1000; % 最大迭代次数
expose = true;
errors = zeros(k, 1);
%% 初始化聚类中心
n = length(target);
loc = randperm(n); % 打乱数据序列
centroids = data([loc(1),loc(2)],:); % 随机选取2个簇心
%% main
labels = zeros(n, 1);
for it=1:N_iter
%% classifation and label
for i=1:n
dists = sqrt(sum((data(i,:) - centroids).^2, 2)); % 计算距离
[distMin, idx] = min(dists); % 寻找距离每个簇心的最小距离
labels(i,:) = idx;
end
for j=1:2
%% calculation erros
errors(j, :) = sum(sqrt(sum((data((j==labels), :) - centroids(j, :)).^2, 2)),1);
end
%% ouput
if expose
disp(sum(errors));
end
for j=1:2
%% update centers
centroids(j,:) = mean(data((j==labels),:),1);
end
end
%% 聚类后的数据可视化
figure
scatter(data((labels==1),1),data((labels==1),2), 'r*');
hold on
scatter(data((labels==2),1),data((labels==2),2), 'ko');