KMeans.m%N是数据一共分多少类3%data是输入的不带分类标号的数据9x2%u是每一类的中心,随机产生3x2%re是返回的带分类标号的数据function [u re]=KMeans(data,N) [m n]=size(data); %m是数据个数,n是数据维数,比如现在有3类数据,9个点,都是二维的数据(1 1)(1 2)(2 1)、(9 9)(8 8)(7 7)、(9 1)(9 2)(8 2) ma=zeros(1,n); %每一维最大的数(9 9) mi=zeros(1,n); %每一维最小的数(1 1) u=zeros(N,n); %随机初始化,最终迭代到每一类的中心位置3x2 for i=1:n ma(i)=max(data(:,i)); %每一维最大的数(9 9) mi(i)=min(data(:,i)); %每一维最小的数(1 1) for j=1:N u(j,i)=ma(i)+(mi(i)-ma(i))*rand(); %随机初始化,不过还是在每一维[min max]中初始化好些,就是一个长方形框 end end while 1 %1是判断表达式 1永远为真 即永远循环 但循环必须是有限 循环体中必须存在终止循环语句break PRe_u=u; %上一次求得的中心位置 3x2,后面的u会变化(公式2),这里先用一个新变量保存下 for i=1:N %第一类到第三类 tmp{i}=[]; % 公式一中的x(i)-uj,为公式一实现做准备!!!!!。这个是单元数组,分配三个cell单元 for j=1:m %1到9个数据 tmp{i}=[tmp{i};data(j,:)-u(i,:)]; %9个数据都和第一个、第二个、第三个中心位置相减, %如果没有[tmp{i};得到的单元数组是1x2的,因为被覆盖掉了,只有第九个数据和类别中心相减的结果 %这个就是有点像累加器,循环得到下一个相减的坐标就累加到原来单元的下面,最后每个类别得到9x2的矩阵 end end quan=zeros(m,N); % 9x3 for i=1:m %公式一的实现 i表示1到9的数据个数 c=[]; %循环一次后c又被清空 for j=1:N %类别一到类别三,tmp有3个单元 c=[c norm(tmp{j}(i,:))]; %norm是范数,这里2范数,是距离,向量的模长,坐标差模长就是距离,[c ]还是累加器的功能,(i,:)不要覆盖 end %第一个循环结束,第一个数据离3个坐标中心的距离形成3x1数组 [junk index]=min(c); %junk是c的最小值,index表示最小值出现的位置,也就是应该分到第几类 quan(i,index)=norm(tmp{index}(i,:)); %quan的i行index列,赋值为距离 end %quan被填满了,每行有2个位置是0 for i=1:N %公式二的实现,类别一到类别三 for j=1:n %第一维到第二维,,u是3行2列 u(i,j)=sum(quan(:,i).*data(:,j))/sum(quan(:,i)); %其实应该是按照距离加权求新质心的坐标 end end if norm(pre_u-u)<0.1 %不断迭代直到位置不再变化 break; end end re=[]; %re是返回的带分类标号的数据 for i=1:m tmp=[]; for j=1:N tmp=[tmp norm(data(i,:)-u(j,:))]; end [junk index]=min(tmp); %说距离是垃圾junk,没用的不关心,只关心是距离拿一个分类中心更近 re=[re;data(i,:) index]; % 每一行是原始数据和分类标号 end end以上是算法
以下是实例
数据是三维的
clear all;close all;clc;%第一类数据mu1=[0 0 0]; %均值S1=[0.3 0 0;0 0.35 0;0 0 0.3]; %协方差 3x2data1=mvnrnd(mu1,S1,100); %产生高斯分布数据%%第二类数据mu2=[1.25 1.25 1.25];S2=[0.3 0 0;0 0.35 0;0 0 0.3];data2=mvnrnd(mu2,S2,100);%第三个类数据mu3=[-1.25 1.25 -1.25];S3=[0.3 0 0;0 0.35 0;0 0 0.3];data3=mvnrnd(mu3,S3,100);%显示数据plot3(data1(:,1),data1(:,2),data1(:,3),'+'); %plot3是三维的图,所以你后面参数必须有三个,data1的三维拆开来写hold on;plot3(data2(:,1),data2(:,2),data2(:,3),'r+');plot3(data3(:,1),data3(:,2),data3(:,3),'g+');grid on;%三类数据合成一个不带标号的数据类data=[data1;data2;data3]; %这里的data是不带标号的%k-means聚类[u re]=KMeans(data,3); %最后产生带标号的数据,标号在所有数据的最后[m n]=size(re); %最后显示聚类后的数据%u是每一类的中心,%re是返回的带分类标号的数据figure;hold on;for i=1:m if re(i,4)==1 %m个数据里面,每个数据xyz三个轴参数,第四个是分类标号 plot3(re(i,1),re(i,2),re(i,3),'ro'); elseif re(i,4)==2 plot3(re(i,1),re(i,2),re(i,3),'go'); else plot3(re(i,1),re(i,2),re(i,3),'bo'); endendgrid on;
新闻热点
疑难解答