MATLAB数学建模——k-means++及可视化

本文介绍了如何使用K-means++算法对多组随机生成的数据集进行聚类,并通过肘部法则确定最优聚类数。文中详细展示了计算过程,包括数据标准化、聚类中心初始化、迭代更新以及聚类结果的可视化。
摘要由CSDN通过智能技术生成
% data set;随机初始化一个数据集
clc;clear;
% Sigma = [1, 0; 0, 1];
% mu1 = [1, -1];
% x1 = mvnrnd(mu1, Sigma, 1000);
% mu2 = [5, -4];
% x2 = mvnrnd(mu2, Sigma, 1000);
% mu3 = [1, 4];
% x3 = mvnrnd(mu3, Sigma, 1000);
% mu4 = [6, 4];
% x4 = mvnrnd(mu4, Sigma, 1000);
% mu5 = [7, 0.0];
% x5 = mvnrnd(mu5, Sigma, 1000);


x1 = randn(1000,6);
x2 = randn(1000,6)+1;
x3 = randn(1000,6)+2;
x4 = randn(1000,6)+3;
x5 = randn(1000,6)+4;

X = [x1;x2;x3;x4;x5];
func_zbf(X,8);
[idx,mu,d] = func_k_means_pro(X,5,1); % 使用自定义的K-means++函数
function func_zbf(X,max_k)
%%% ZBF:肘部法,作出不同K值聚类偏差图
% X:数据矩阵
% max_k:最大聚类数

dk = zeros(max_k,2); % 初始化聚类数及对应的偏差矩阵
for i = 1 : max_k % 最小聚类数设置为1
    [L,~,D] = func_k_means_pro(X,i,0);
%       [L,~,~,D] =kmeans(zscore(X),i);  
    for j = 1 : i
        d = D(:,j);
        tD1 = L < j; 
        tD2 = L > j;
        tD = tD1 + tD2;
        tD = all(tD,2);
        d(tD,:) = [];
        dk(i,2) = dk(i,2) + sum(d.^2);
    end
    dk(i,1) = i;
end

figure
plot(dk(2:end,1),dk(2:end,2),'-','LineWidth',1.2,'Color','b')
hold on
grid off
plot(dk(2:end,1),dk(2:end,2),'or','markerfacecolor', 'c',"LineWidth",1.1);
% title('不同K值聚类偏差图') 
set(gca, 'linewidth', 1.1, 'fontsize', 14, 'fontname', '宋体')
xlabel('分类数(K值)') 
ylabel('簇内误差平方和') 
function [indexs, mu, D] = func_k_means_pro(X,k,trigger)
%%% K_MEANS_PRO: k-means++聚类
% X: 数据集,每一行为一条数据
% k: 聚类数
% mu: 最终的聚类中心
% D: 数据点与各聚类中心的距离
% indexs: 数据所对应的类别
% trigger: 选择是否可视化

%% 数据标准化(可选)
X = zscore(X);
% X = (mapminmax(X',0,1))';

%% 获取数据总数
[n,length] = size(X);

%% 随机选择一个数据点作为第一个聚类中心
init_mu = X(randperm(size(X, 1), 1), :);
% 选择剩余的聚类中心
for i = 2 : k
    % 计算各数据点与已有聚类中心的平方欧式距离
    Dis = pdist2(X, init_mu, 'squaredeuclidean'); 
    Dis = min(Dis, [], 2); % 找出各数据点与最近聚类中心的平方欧式距离
    Dis = Dis / sum(Dis); % 计算各数据点被选为下一个聚类中心的概率
    %{ 
    如果累积概率大于随机数,则选取该点为新的聚类中心,确保初始聚类中心间的
    距离足够大
    %}
%     init_mu(i, :) = X(find(rand < cumsum(Dis), 1), :); 
    init_mu(i, :) = X(find(Dis == max(Dis), 1), :); 
end

%% 计算迭代,更新聚类中心
indexs = zeros(n, 1);
mu = init_mu;
new_mu = mu;
eps = 1e-6; % 设置精度
delta = 1;
while (delta > eps) % 若聚类中心不再变化则终止迭代
    mu = new_mu;
    for i =1:n
        y = repmat(X(i, :), k, 1);
        dist = y - mu;
        d = sum(dist.*dist,2); % 计算欧式距离
        j = find(d==min(d)); % 寻找最小距离对应的聚类中心
        indexs(i) = j;
    end
    for j = 1 : k
        order = indexs == j;
        new_mu(j, :) = mean(X(order, :), 1); % 以均值作为新的聚类中心
    end

    % 计算新旧聚类中心的偏移距离
    delta = sqrt(sum(sum((mu-new_mu).*(mu-new_mu))));
end

%% 根据最终聚类中心确定样本聚类
indexs = zeros(n, 1);
for i = 1 : n
    R = repmat(X(i,:),k,1) - mu;
    Res = sum(R.*R,2);
    j = find(Res == min(Res));
    indexs(i) = j;
end

%% 计算数据点与各个聚类中心的距离
D = zeros(n,k);
for i = 1 : n
    for j = 1 : k
        d = X(i,:)-mu(j,:);
        D (i,j) = sqrt(sum(d.^2,2));
    end
end

%% 将数据投影到二维平面,画出聚类结果图
if trigger == 1
    new_mu = mu;
    new_X = X;
    if length > 2 % 若为高维数据,则通过主成分分析投影到二维平面
        [~, score, ~, ~, ~, ~]=pca(X);
        new_X=score(:,1:2);   % 取转换后的矩阵score的前k列为PCA降维后特征
        new_mu = new_mu * (new_X\X)';
    end
    colours = ['r','g','b','m','k','y','c','w'];
    figure
    hold on
    grid off
    set(gca, 'linewidth', 1.1, 'fontsize', 14, 'fontname', '宋体')
    for i = 1 : k
        for j = 1 : n
            if indexs(j) == i
                plot(new_X(j,1),new_X(j,2),'.','Color',colours(i),'LineWidth',1)
            end
        end
        plot(new_mu(i,1),new_mu(i,2),'o','Color','#A500EB','markerfacecolor', colours(i),'LineWidth',2)
    end
    if length > 2
        xlabel("投影指标1")
        ylabel("投影指标2")
    else
        xlabel("指标1")
        ylabel("指标2")    
    end
end
end

结果如下图所示:

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值