【K-Means】鸢尾花的分类聚类

鸢尾花的分类聚类

现有若干鸢尾花的数据,每朵鸢尾花有4个数据,分别为萼片长(单位:厘米)、萼片宽(单位厘米)、花瓣长度(单位厘米)和花瓣宽(单位厘米)。我们希望能找到可行的方法可以按每朵花的4个数据的差异将这些鸢尾花分成若干类,让每一类尽可能的准确,以便帮助植物专家对这些花进行进一步的分析。


这是一道数模入门题目。

无指导聚类。用K-Means算法,最简单的欧式距离,最简单的平均位置计算方法,然而效果已经很好。

可视化采用平行坐标轴法,并手动调整了主次。


第一次用Matlab,颠覆了思维,感觉是对以前的程式化的思维的一个强力冲击。使用上比C++简洁很多很多。强烈渴望继续学习下去。

main.m:

clear all;
close all;
clc;

dat=[4.8 3.1 1.6 0.2; 
 5.4 3.4 1.5 0.4; 
 5.2 4.1 1.5 0.1; 
 5.5 4.2 1.4 0.2; 
 4.9 3.1 1.5 0.2; 
 5.0 3.2 1.2 0.2; 
 5.5 3.5 1.3 0.2; 
 4.9 3.6 1.4 0.1; 
 4.4 3.0 1.3 0.2; 
 5.1 3.4 1.5 0.2; 
 5.0 3.5 1.3 0.3; 
 4.5 2.3 1.3 0.3; 
 4.4 3.2 1.3 0.2; 
 5.0 3.5 1.6 0.6; 
 5.1 3.8 1.9 0.4; 
 4.8 3.0 1.4 0.3; 
 5.1 3.8 1.6 0.2; 
 4.6 3.2 1.4 0.2; 
 5.3 3.7 1.5 0.2; 
 5.0 3.3 1.4 0.2; 
 7.0 3.2 4.7 1.4; 
 6.4 3.2 4.5 1.5; 
 6.9 3.1 4.9 1.5; 
 5.5 2.3 4.0 1.3; 
 6.5 2.8 4.6 1.5; 
 5.7 2.8 4.5 1.3; 
 6.3 3.3 4.7 1.6; 
 4.9 2.4 3.3 1.0; 
 6.6 2.9 4.6 1.3; 
 5.2 2.7 3.9 1.4; 
 5.0 2.0 3.5 1.0; 
 5.9 3.0 4.2 1.5; 
 6.0 2.2 4.0 1.0; 
 6.1 2.9 4.7 1.4; 
 5.6 2.9 3.9 1.3; 
 6.7 3.1 4.4 1.4; 
 5.6 3.0 4.5 1.5; 
 5.8 2.7 4.1 1.0; 
 6.2 2.2 4.5 1.5; 
 5.6 2.5 3.9 1.1; 
 5.9 3.2 4.8 1.8; 
 6.1 2.8 4.0 1.3; 
 6.3 2.5 4.9 1.5; 
 6.1 2.8 4.7 1.2; 
 6.4 2.9 4.3 1.3; 
 6.6 3.0 4.4 1.4; 
 6.8 2.8 4.8 1.4; 
 6.7 3.0 5.0 1.7; 
 6.0 2.9 4.5 1.5; 
 5.7 2.6 3.5 1.0; 
 5.5 2.4 3.8 1.1; 
 5.5 2.4 3.7 1.0; 
 5.8 2.7 3.9 1.2; 
 6.0 2.7 5.1 1.6; 
 5.4 3.0 4.5 1.5; 
 6.0 3.4 4.5 1.6; 
 6.7 3.1 4.7 1.5; 
 6.3 2.3 4.4 1.3; 
 5.6 3.0 4.1 1.3; 
 5.5 2.5 5.0 1.3; 
 5.5 2.6 4.4 1.2; 
 6.1 3.0 4.6 1.4; 
 5.8 2.6 4.0 1.2; 
 5.0 2.3 3.3 1.0; 
 5.6 2.7 4.2 1.3; 
 5.7 3.0 4.2 1.2; 
 5.7 2.9 4.2 1.3; 
 6.2 2.9 4.3 1.3; 
 5.1 2.5 3.0 1.1; 
 5.7 2.8 4.1 1.3; 
 6.3 3.3 6.0 2.5; 
 5.8 2.7 5.1 1.9; 
 7.1 3.0 5.9 2.1; 
 6.3 2.9 5.6 1.8; 
 6.5 3.0 5.8 2.2; 
 7.6 3.0 6.6 2.1; 
 4.9 2.5 4.5 1.7; 
 7.3 2.9 6.3 1.8; 
 6.7 2.5 5.8 1.8; 
 7.2 3.6 6.1 2.5; 
 6.5 3.2 5.1 2.0; 
 6.4 2.7 5.3 1.9; 
 6.8 3.0 5.5 2.1; 
 5.7 2.5 5.0 2.0; 
 5.8 2.8 5.1 2.4; 
 6.4 3.2 5.3 2.3; 
 6.5 3.0 5.5 1.8; 
 7.7 3.8 6.7 2.2; 
 7.7 2.6 6.9 2.3; 
 6.0 2.2 5.0 1.5; 
 6.9 3.2 5.7 2.3; 
 5.6 2.8 4.9 2.0; 
 7.7 2.8 6.7 2.0; 
 6.3 2.7 4.9 1.8; 
 6.7 3.3 5.7 2.1; 
 7.2 3.2 6.0 1.8; 
 6.2 2.8 4.8 1.8; 
 6.1 3.0 4.9 1.8; 
 6.4 2.8 5.6 2.1; 
 7.2 3.0 5.8 1.6; 
 7.4 2.8 6.1 1.9; 
 7.9 3.8 6.4 2.0; 
 6.4 2.8 5.6 2.2; 
 6.3 2.8 5.1 1.5; 
 6.1 2.6 5.6 1.4; 
 7.7 3.0 6.1 2.3; 
 6.3 3.4 5.6 2.4; 
 6.4 3.1 5.5 1.8; 
 6.0 3.0 4.8 1.8; 
 6.9 3.1 5.4 2.1; 
 6.7 3.1 5.6 2.4; 
 6.9 3.1 5.1 2.3; 
 5.8 2.7 5.1 1.9; 
 6.8 3.2 5.9 2.3; 
 6.7 3.3 5.7 2.5; 
 6.7 3.0 5.2 2.3; 
 6.3 2.5 5.0 1.9; 
 6.5 3.0 5.2 2.0; 
 6.2 3.4 5.4 2.3; 
 5.9 3.0 5.1 1.8];

hold on;
[m n]=size(dat);
for i=1:m
    line(1:n,dat(i,[2 1 3 4]));%原始数据按照平行坐标系展示,观察发现大致分为三类。
end
figure;
hold on;
K=3;
rs = kmean(dat,K);%进行无指导聚类
ou1=[];
ou2=[];
ou3=[];
for i=1:m%聚类后的数据
    if rs(i,1) == 1
        ou1 = [ou1;i];
        line(1:n,dat(i,[2 1 3 4]),'Color','r');
    elseif rs(i,2) == 1
        ou2 = [ou2;i];
        line(1:n,dat(i,[2 1 3 4]),'Color','g');
    else
        ou3 = [ou3;i];
        line(1:n,dat(i,[2 1 3 4]),'Color','b');
    end
end

fid = fopen('classify.txt','wt');
[ss a] = size(ou1);
fprintf(fid,'第一类');
for i=1:ss
    fprintf(fid,'%d ',ou1(i));
end
fprintf(fid,'\n第二类');
[ss a] = size(ou2)
for i=1:ss
    fprintf(fid,'%d ',ou2(i));
end
fprintf(fid,'\n第三类');
[ss a] = size(ou3)
for i=1:ss
    fprintf(fid,'%d ',ou3(i));
end

fclose(fid);

Kmeans.m:

function re=kmean(dat,K)%K-平均值算法进行无指导聚类
    [m n] = size(dat);
    u = zeros(K,n);
    for i=1:n
        mi = min(dat(:,i));
        ma = max(dat(:,i));
        for j=1:K
            u(j,i) = mi+(ma-mi)*rand();%使种子点每一维都在该维最大值和最小值之间
        end
    end
    
    dist = zeros(K,1);
    while 1
        re = zeros(m,K);
        uu = u;%记录之前的种子点
        for i=1:m
            for j=1:K
                dist(j) = sum((dat(i,:)-u(j,:)).^2);%用欧式距离公式计算每个点到每个种子点的距离
            end
            [mm pp] = min(dist(:));%找到每个点最近的种子点
            re(i,pp) = 1;%记录分组中有的点
        end
        
        for i=1:K
            for j=1:n
                ss = sum(re(:,i));
                if ss~=0
                    u(i,j) = sum(re(:,i).*dat(:,j))/sum(re(:,i));%利用每一组中有的点的,各维平均值更新种子点的各维的值
                end
            end
        end
        
        if norm(uu-u)<0.1%如果种子点的坐标最后收敛,则退出循环
            break;
    end
end


你可能感兴趣的:(数模)