实验三 :k-means聚类方法

一、实验目的

掌握有关k-means聚类方法的理论知识,通过反复迭代改变分组的重定位,让同一个簇当中的对象尽可能“相似”,不同簇中的对象尽可能“相异”。

二、实验任务

对k-means聚类方法进行编码计算,实例如下:

三、实验过程

1.k-means算法模型介绍:


四、实验结果

实现平台:Matlab 2022A
实验代码:

clc; clear; close all;

% 初始化数据
%书上数据
data(:,1) = [1, 5, 10, 9, 26, 32, 16, 21, 14];
data(:,2) = [0, 0, 0, 0, 0, 0, 0, 0, 0];
%随机大量二维数据
%data(:,1) = randi([0, 100], 100, 1);
%data(:,2) = randi([0, 100], 100, 1);


% 绘制原始数据散点图
figure(1)
scatter(data(:,1),data(:,2),'LineWidth',2)
title("原始数据散点图")

% 设置聚类数
cluster_num = 3;

% 调用K-Means算法进行聚类
[index_cluster, cluster, E] = kmeans_func(data, cluster_num);

% 绘制聚类效果图
figure(2)
a = unique(index_cluster); % 找出分类出的个数
C = cell(1,length(a));
for i = 1:length(a)
   C{1,i} = find(index_cluster == a(i)); % 将相同簇的索引存储在C中
end
for j = 1:cluster_num
    data_get = data(C{1,j},:);
     if j == 1
        scatter(data_get(:,1),data_get(:,2),100,'o','filled','MarkerFaceAlpha',.6,'MarkerEdgeAlpha',.9);
    elseif j == 2
        scatter(data_get(:,1),data_get(:,2),100,'s','filled','MarkerFaceAlpha',.6,'MarkerEdgeAlpha',.9);
    elseif j == 3
        scatter(data_get(:,1),data_get(:,2),100,'^','filled','MarkerFaceAlpha',.6,'MarkerEdgeAlpha',.9);
     end
     hold on
end
% 绘制聚类中心
plot(cluster(:,1),cluster(:,2),'ks','LineWidth',2);
hold on

% 计算并显示轮廓系数
sc_t = mean(silhouette(data, index_cluster'));
title_str = ['原理推导K均值聚类', '  聚类数为:', num2str(cluster_num), '  SC轮廓系数:', num2str(sc_t), '  准则函数E:', num2str(E)];
title(title_str)

% K-Means算法实现
function [index_cluster, cluster, E] = kmeans_func(data, cluster_num)
    % 原理推导Kmeans聚类算法
    [m, n] = size(data); % 获取数据的行数和列数
    cluster = data(randperm(m, cluster_num), :); % 从m个点中随机选择cluster_num个点作为初始聚类中心点
    epoch_max = 1000; % 最大迭代次数
    therad_lim = 0.001; % 中心变化阈值
    epoch_num = 0; % 迭代次数初始化
    E = inf; % 初始化准则函数E

    while (epoch_num < epoch_max)
        epoch_num = epoch_num + 1; % 迭代次数加1
        
        % distance1存储每个点到各聚类中心的欧氏距离
        for i = 1:cluster_num
            distance = (data - repmat(cluster(i,:), m, 1)).^2;
            distance1(:, i) = sqrt(sum(distance, 2));
        end
        [~, index_cluster] = min(distance1, [], 2); % 找到每个点距离最近的聚类中心
        
        % cluster_new存储新的聚类中心
        for j = 1:cluster_num
            cluster_new(j, :) = mean(data(find(index_cluster == j), :)); % 计算新的聚类中心
        end
        
        % 计算当前聚类结果的准则函数E
        E_new = 0;
        for j = 1:cluster_num
            E_new = E_new + sum(sum((data(find(index_cluster == j), :) - cluster(j, :)).^2));
        end
        
        % 如果新的聚类中心和上一轮的聚类中心距离和大于阈值,更新聚类中心,否则算法结束
        if (sqrt(sum((cluster_new - cluster).^2, 'all')) > therad_lim)
            cluster = cluster_new; % 更新聚类中心
            E = E_new; % 更新准则函数E
        else
            break; % 跳出循环,算法结束
        end
    end
end

实验结果:
①基本结果
运行书上实例

②额外结果
计算数据量更大的二维数据实例

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐