聚类算法小结(1)——K均值聚类算法

因为笔者最近在处理数据的时候需要用到分类算法,为了理解的更加透彻,在这里对几种基本的分类算法进行了小结,以下所有的工作都是在已有的基础上加入了自己的一些理解

K均值聚类算法

在看下面之前建议看大佬写的Kmeans聚类算法详解,个人觉得写的很详细,也比较容易理解,以下的都是在此基础上的一些个人感悟。

k均值聚类算法(k-means clustering
algorithm)是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。

对数据分类的原因在这里就不再赘述了,简要说说什么是分类,谈谈个人的理解
所谓分类就是将一堆看似无关的数据基于某种标准划分成不同的类别,例如全世界的人口,按照性别这一标准,可以划分成男人和女人;按照是否十八岁,可以划分成未成年人和成年人;标准不同,所得到的类别也不同。
回归到正题上,**K均值聚类算法的分类标准就是将离中心点最近的点划分为一类(基于欧式距离)**所以K均值聚类算法的核心为以下两点:

  1. 聚类中心的选取,因为K均值聚类的原理很简单,所以初始聚类中心的选取就显得格外重要;
  2. 类别的划分,基于欧式距离来判断点与点之间的远近。

核心原理

给定一个数据集X(n*m的一个矩阵,无标签,无ID)
在这里插入图片描述
数据集X一共有n条数据,每一条数据有m条特征。

首先初始化K个聚类中心(如何初始化这里不再赘述,方法有很多,感兴趣的可以自行查找)[C1,C2,C3,…,CK],即聚类矩阵为
在这里插入图片描述
其中
在这里插入图片描述

比较每个点(即每条数据)与K个聚类中心的距离,将即归入距离最近的一类中(若某一点距离不同的聚类中心的距离相等,则随机归入一类,因为会对聚类中心进行迭代),距离公式如下:
在这里插入图片描述
其中
在这里插入图片描述
更直观的
在这里插入图片描述
通过比较数据点到各数据中心的距离,将其归入距离最近的类别中。
例如在上图中,该数据点距离第5个聚类中心最近,所以将该数据点归入第二类。
不断重复上述操作,将所有数据点分类完毕后,即可得到K类数据。
接下来就是聚类中心的更新
分类结果如下图所示{S1,S2,…,SK},S1表示第一类所有数据点的集合
在这里插入图片描述
接下来需要对每一类的聚类中心进行更新,类簇中心就是类簇内所有对象在各个维度的均值,更新公式为
在这里插入图片描述
其中|S_i|表示第i类中数据点的个数,更新后的聚类中心与更新前之间也会有距离,如下图所示
在这里插入图片描述
迭代终止的标准:类簇中心的变化很小(即d1+d2+…+dk的和很小,小于某个值,这个值一般是人为给,d_i是指第i类中更新前后聚类中心的距离)或者达到了迭代次数(有可能前一条件无法满足,避免无限迭代)
综上所述,算法的主要思路如下(基于MATLAB)

1.初始化聚类中心
2.更新聚类中心,迭代
3.判断是否达到终止标准,终止迭代
4.输出结果
主要程序

%% Kmeans算法
% 输入:
% data 输入的不带分类标号的数据
% K 数据一共分多少类
% iniCentriods 自行指定初始聚类中心
% iterations 迭代次数,防止迭代次数太多造成死循环

% 输出:
% Idx 返回的分类标号,与数据一一对应
% centroids 每一类的中心
% Distance 类内总距离

%迭代终止的标准:当类簇中心点的变化很小,或者达到指定的迭代次数

function [Idx,centroids,Distance]=SelfKMeans(data,k,iniCentriods,iterations)
[numofData,numofAttr]=size(data);%numofData是数据个数,即行数,numofAttr是数据维数,即列数
%% 初始化聚类中心
centroids=iniCentriods;
%% 迭代
for iter=1:iterations %开始迭代,直到达到指定的迭代次数
    pre_centroids=centroids;%上一次求得的中心位置
    tags=zeros(numofData,k);%标签矩阵,用来记录数据属于第几类
    %% 寻找最近中心,更新中心
    for i=1:numofData %遍历每一条数据
        D=zeros(1,k);%每个数据点与每个聚类中心的标准差
        Dist=D;
        %% 计算每个点到每个中心点的标准差,一共有k个中心点
        for j=1:k
            Dist(j)=norm(data(i,:)-centroids(j,:),2);
        end
        [minDistance,index]=min(Dist);%寻找距离最小的类别索引
        tags(i,index)=1;%标记最小距离所处的位置(类别)
    end
    %% 取均值更新聚类中心点
    for i=1:k
        if sum(tags(:,i))~=0
            %未出现空类,计算均值作为下一聚类中心
            for j=1:numofAttr
                centroids(i,j)=sum(tags(:,i).*data(:,j))/sum(tags(:,i));
            end 
        else
            %如果出现空类,从数据集中随机选中一个点作为中心
            randidx=randperm(size(data,1));%生成一个n维的向量,每个值都小于等于n
            centroids(i,:)=data(randidx(1),:);
            tags(randidx,:)=0;
            tags(randidx,i)=1;
        end
    end
    if sum(norm(pre_centroids-centroids,2))<0.001 %不断迭代直到位置不再变化
       break
    end
end
%% 计算输出结果
Distance=zeros(numofData,1);
Idx=zeros(numofData,1);
for i=1:numofData
    D=zeros(1,k);%每个数据点与每一个聚类中心的标准差
    Dist=D;
    %% 计算每个点到每个中心点的标准差
    for j=1:k
        Dist(j)=norm(data(i,:)-centroids(j,:),2);
    end
    [distance,idx]=min(Dist);%寻找距离最小的类别索引
    distance=Dist(idx);
    Distance(i)=distance;
    Idx(i)=idx;
end
Distance=sum(Distance,1);%计算类内总距离
end

运行结果
在这里插入图片描述
虽然现在很多语言都自带kmeans函数,但是自编一下kmeans函数对理解该算法还是有很大的好处的,当然由于初始聚类中心选取的不一样,自编的kmeans函数与软件自带的kmeans函数还是会有误差的,相关数据集已经打包整理好了,有需要的可以下载直接运行即可

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值