MATLAB实现K-means聚类数学建模算法

本文详细介绍了K-means聚类算法的工作原理,包括步骤、优点和局限性,以及如何在MATLAB中实现该算法。特别关注了如何选择初始簇中心和调整簇数的问题。最后通过示例展示了算法的运行结果和性能评估指标。
摘要由CSDN通过智能技术生成

K-means聚类是一种常用的无监督学习算法,用于将数据集中的观测点划分为不同的组或簇。这个算法的目标是将数据点分配到k个簇中,使得每个数据点到其所属簇的中心的距离最小化。

算法的步骤如下:

1. **选择簇的数量(k):** 首先,需要指定希望将数据分成的簇的数量。这可以是预先设定的,也可以通过一些启发式方法确定。

2. **初始化簇中心:** 随机选择k个数据点作为初始的簇中心。

3. **分配数据点:** 对于每个数据点,将其分配给离它最近的簇中心。

4. **更新簇中心:** 对于每个簇,计算其所有成员的平均值,并将该平均值作为新的簇中心。

5. **重复步骤3和步骤4:** 重复执行步骤3和步骤4,直到簇中心不再发生显著变化或达到预定的迭代次数。

K-means算法的优点包括简单易实现,计算效率高。然而,它对初始簇中心的选择敏感,并且对异常值和噪声敏感。

这个算法通常用于聚类分析,图像分割,以及其他需要将数据点划分成不同组的任务。需要注意的是,选择合适的簇数是一个关键问题,有时需要通过实验或其他方法进行调优。

MATLAB的代码如下:


% data set;
Sigma = [1, 0; 0, 1];
mu1 = [1, -1];
x1 = mvnrnd(mu1, Sigma, 200);
mu2 = [5, -4];
x2 = mvnrnd(mu2, Sigma, 200);
mu3 = [1, 4];
x3 = mvnrnd(mu3, Sigma, 200);
mu4 = [6, 4];
x4 = mvnrnd(mu4, Sigma, 200);
mu5 = [7, 0.0];
x5 = mvnrnd(mu5, Sigma, 200);
X = [x1; x2; x3; x4; x5];
X_label = [ones(200, 1); 2 * ones(200, 1); 3 * ones(200,1); 4 * ones(200, 1);5 * ones(200, 1)];
% Show the data points 
plot(x1(:,1), x1(:,2), 'r.'); hold on;
plot(x2(:,1), x2(:,2), 'b.');
plot(x3(:,1), x3(:,2), 'k.');
plot(x4(:,1), x4(:,2), 'g.');
plot(x5(:,1), x5(:,2), 'm.');
% select initial clustering center
m = 30;
a = max(X);
b = min(X);
k=5;
mu = zeros(k,2*m);
r = zeros(m,1);
for t=1:m
    for i=1:k
        mu(i,2*t-1:2*t)=[a(1)+(b(1)-a(1))*rand,a(2)+(b(2)-a(2))*rand];
    end
    for j = 1 : 1000
        R = repmat(X(j, :), k, 1) - mu(:,2*t-1:2*t);
        r(t) = r(t) + sum(sum(R.*R));
    end
end
p = find(r==min(r));
mu = mu(:,2*p-1:2*p);
label = zeros(1000, 1);
mu_new = mu;
eps = 1e-6;
delta = 1;
while (delta > eps)
    mu = mu_new;
    for i =1:1000
        y = repmat (X(i, :), k, 1);
        dist = y - mu;
        d = sum(dist.*dist,2);
        j = find(d==min(d));
        label(i) = j;
    end
    for j = 1 : k
        order = find(label == j);
        mu_new(j, :) = mean(X(order, :), 1);
    end
    delta = sqrt(sum(sum((mu-mu_new).*(mu-mu_new))));
end
label = zeros(1000, 1);
for i = 1 : 1000
    R = repmat(X(i,:),k,1) - mu;
    Residual = sum(R.*R,2);
    j = find(Residual == min(Residual));
    label(i) = j;
end
% Construct map function
s = zeros(k, 1);
for j =1 : k
    order = find(label==j);
    Y = X_label(order);
    s(j) = mode(Y);
end
map_label =zeros(1000, 1);
for j = 1 : k
    map_label(label==j) = s(j);
end
figure;
hold on;
for i =1:1000
    if map_label(i)==1
        plot(X(i,1),X(i,2),'r.');
    elseif map_label(i)==2
        plot(X(i,1),X(i,2),'b.');
    elseif map_label(i)==3
        plot(X(i,1),X(i,2),'k.');
    elseif map_label(i)==4
        plot(X(i,1),X(i,2),'g.');
    else
        plot(X(i,1),X(i,2),'m.');
    end
end
% show the cluster center
for i = 1 : 5
    plot(mu(i,1),mu(i,2),'yo','LineWidth',3);
end
% Calculate NMI(Normalized Mutual Information)
d = zeros(5, 1);
g = d;
sigma = zeros(5,5);
numerator = 0;
denominator1 = 0;
denominator2 = 0;
for i = 1 : 5
    d(i) = length(find(map_label==i));
    g(i) = length(find(X_label==i));
end
for i = 1 : 5 
    for j = 1 : 5
        order = find(map_label==i);
        sigma(i,j) = length(find(X_label(order)==j));
        if sigma(i,j)~=0
            numerator = numerator + sigma(i,j).*log(1000.*sigma(i,j)./(d(i).*g(j)));
        end
    end
end

for i = 1 : 5
    if d(i)~=0
        denominator1 = denominator1 + d(i).*log(d(i)/1000);
    end
    if g(i)~=0
        denominator2 = denominator2 + g(i).*log(g(i)/1000);
    end
end
denominator = sqrt(denominator1 * denominator2);
NMI = numerator/denominator;
fprintf('NMI=%.3f\n',NMI);
accuracy = sum(map_label == X_label)/1000;
fprintf('accuracy=%.3f\n',accuracy);




运行结果如下:

 

 

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
k-means算法是一种常用的聚类算法,用于将样本分成k个簇。在Matlab中,可以使用Kmeans函数来实现k-means算法。该函数接受以下参数: - sample:需要进行聚类的样本 - k:划分的簇的个数 - threshold:差异度阈值 - n:最大迭代次数 函数会返回以下结果: - index:聚类后每个样本的标记 - C:k个簇的中心 - sumd:样本点到相应簇心的距离 在Kmeans函数中,首先会随机选择k个样本作为初始的簇心。然后,使用欧氏距离(可以根据需求使用其他距离度量)计算每个样本与各个簇心的距离,将样本划分到距离最近的簇中。接着,重新计算每个簇的中心,并检查簇心的变化是否小于阈值。如果满足条件,算法结束;否则,重复以上步骤,直到达到最大迭代次数或簇心不再发生变化。 为了辅助分析聚类效果,可以使用Visualize_SSE函数来绘制SSE随k值变化的图像。该函数接受两个参数:样本和k值。函数会计算每个k值对应的SSE(平方和误差),并将其绘制成图像,横轴为k值,纵轴为SSE值。 需要注意的是,上述代码中还包含了一个计算距离的函数cal_dist,用于计算两个样本之间的闵可夫斯基距离(欧氏距离的一种推广)。你也可以使用Matlab中自带的pdist或者norm函数来计算距离。 综上所述,你可以使用以上提供的代码来实现k-means算法,并根据需要使用Visualize_SSE函数进行结果可视化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [k-means聚类算法matlab实现(简单实现)](https://blog.csdn.net/qq_43812171/article/details/106301439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI Dog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值