实验目的:
了解掌握 K-means 聚类方法
硬件环境:
笔记本电脑
软件环境:
Octive
实验步骤与内容:
K-means 算法是一个迭代式的算法,是无监督学习算法。算法过程为:
(1)所有的观测实例中随机抽取出 k 个观测点,作为聚类中心点,然后遍历其余的观测点
找到距离各自最近的聚类中心点,将其加入到该聚类中。这样就有了一个初始的聚类结果,
这是一次迭代的过程。
(2)每个聚类中心都至少有一个观测实例,可以求出每个聚类的中心点(means),作为新
的聚类中心,然后再遍历所有的观测点,找到距离其最近的中心点,加入到该聚类中。然后
继续运行(2)。
(3)如此往复(2),直到前后两次迭代得到的聚类中心点一模一样。
这样得到的 k 个聚类中心,和距离它们最近的观测点构成 k 个聚类,得到需要的结果。
K-means 算法的工作流程
随机确定 k 个初始点的质心;将数据集中的每一个点分配到一个簇中,即为每一个点找到距
其最近的质心,并将其分配给该质心所对应的簇;该步完成后,每一个簇的质心更新为该簇
所有点的平均值。伪代码如下:
创建 k 个点作为起始质心,可以随机选择(位于数据边界内)
当任意一个点的簇分配结果发生改变时
对数据集中每一个点
对每个质心
计算质心与数据点之间的距离
将数据点分配到距其最近的簇
对每一个簇,计算簇中所有点的均值并将均值作为质心
实验结果:
结论分析与体会:
通过进行实验学习了 K-means 聚类方法,发现初始类中心的选择对聚类的准确度有较大
的影响,在初始类中心的选择时,最好选择两两距离较大,且能代表不同数据样本类别的点
作为初始的类中心点。初始的聚类中心的不同,对聚类结果没有很大的影响,而对迭代次数
有显著的影响。数据的输入顺序不同,同样影响迭代次数,而对聚类结果没有太大的影响。
附源代码:
clear ; close all; clc
fprintf('\nRunning K-Means clustering on pixels from an image.\n\n');
A = double(imread('bird_small.tiff'));
A = A / 255;
img_size = size(A);
X = reshape(A, img_size(1) * img_size(2), 3);
K = 16;
max_iters = 10;
initial_centroids = kMeansInitCentroids(X, K);
[centroids, idx] = runkMeans(X, initial_centroids, max_iters);
fprintf('Program paused. Press enter to continue.\n');
pause;
fprintf('\nApplying K-Means to compress an image.\n\n');
idx = findClosestCentroids(X, centroids);
X_recovered = centroids(idx,:);
X_recovered = reshape(X_recovered, img_size(1), img_size(2), 3);
subplot(1, 2, 1);
imagesc(A);
title('Original');
subplot(1, 2, 2);
imagesc(X_recovered)
title(sprintf('Compressed, with %d colors.', K));
imwrite(uint8(round(x)), 'x');
fprintf('Program paused. Press enter to continue.\n');
pause;
function centroids = computeCentroids(X, idx, K)
[m n] = size(X);
centroids = zeros(K, n);
for i = 1:K
centroids(i, :) = mean(X(find(idx==i),:));
end
End
function idx = findClosestCentroids(X, centroids)
K = size(centroids, 1);
idx = zeros(size(X,1), 1);
for i = 1:size(X,1)
min = 10.^5;
tempidx = 0;
for j = 1:K
dis = sum((X(i,:) - centroids(j,:)).^2);
if dis
if ~exist('plot_progress', 'var') || isempty(plot_progress)
plot_progress = false;
end
if plot_progress
figure;
hold on;
end
[m n] = size(X);
K = size(initial_centroids, 1);
centroids = initial_centroids;
previous_centroids = centroids;
idx = zeros(m, 1);
for i=1:max_iters
fprintf('K-Means iteration %d/%d...\n', i, max_iters);
if exist('OCTAVE_VERSION')
fflush(stdout);
end
idx = findClosestCentroids(X, centroids);
if plot_progress
plotProgresskMeans(X, centroids, previous_centroids, idx, K, i);
previous_centroids = centroids;
fprintf('Press enter to continue.\n');
pause;
end
centroids = computeCentroids(X, idx, K);
end
if plot_progress
hold off;
end
end