聚类算法

聚类方法主要分为四种:基于划分的聚类、基于层次的聚类、基于密度的聚类、基于网格的聚类。其中基于层次的聚类又分为凝聚式层次聚类和分裂式层次聚类,凝聚式层次聚类就是在初始阶段将每一个点都视为一个簇,之后每一次合并两个最接近的簇;分裂式层次聚类就是在初始阶段将所有的点视为一个簇,之后每次分裂出一个簇,直到最后剩下单个点的簇为止。

常见的聚类算法有:K-means 聚类算法;Mean-Shift (均值漂移)聚类;基于密度的带噪声的空间聚类(DBSCAN);基于高斯混合模型(GMM)的最大期望(EM)聚类;凝聚层次聚类(AHC)。

层次聚类法:以凝聚式层次聚类法为例,初始阶段将每一个点都视为一个簇,计算各个簇之间的距离,将距离最近的两个簇合并为一类,重复以上过程,直到所有样本归为一类。簇间距离的计算方法有以下几种:

1、最小连接距离法:取两个簇中距离最近的两个样本的距离作为这两个簇的距离;

2、最大连接距离法:取两个簇中离的最远的两个点之间的距离作为这两个簇间的距离;

3、平均连接距离法:把两个簇中各点两两间的距离的平均值作为这两个簇的距离。

而以上的“距离”的常用计算方法有:余弦距离、欧式距离、曼哈顿距离。

注:在k-means算法中,如果聚类后某些簇中没有数据,通常选择删除这个类,最终得到k-1个类,实际中这种情况很少发生。为了避免k-means聚类达到局部最优,在聚类中心初始化时可以选择多次随机初始化,选择代价函数值最小的作为最终聚类结果(主要针对k比较小的情况,k很大时多次随机初始化结果改变不大,可能第一次就会达到很好的结果)。

 

各类聚类算法原理介绍:https://blog.csdn.net/Katherine_hsr/article/details/79382249

python实现:https://shuwoom.com/?p=1193(各聚类算法)

https://blog.csdn.net/qq_30262201/article/details/78799926

https://www.cnblogs.com/tiaozistudy/p/dbscan_algorithm.html

matlab代码:

function [IDX, isnoise]=DBS(X,epsilon,MinPts)
    C=0;
    n=size(X,1);
    IDX=zeros(n,1);
    D=pdist2(X,X);
    visited=false(n,1);
    isnoise=false(n,1);
    for i=1:n
        if ~visited(i)
            visited(i)=true;
            
            Neighbors=RegionQuery(i);
            if numel(Neighbors)=MinPts
                    Neighbors=[Neighbors Neighbors2];   %#ok
                end
            end
            if IDX(j)==0
                IDX(j)=C;
            end
            
            k = k + 1;
            if k > numel(Neighbors)
                break;
            end
        end
    end
    
    function Neighbors=RegionQuery(i)
        Neighbors=find(D(i,:)<=epsilon);
    end
end


function plotClusterinResult(X,IDX)
    k=max(IDX);
    Colors=hsv(k);
    Legends={};
    for i=0:k
        Xi=X(IDX==i,:);
        if i~=0
            Style='x';
            MarkerSize=8;
            Color=Colors(i,:);
            Legends{end+1}=['Cluster #' num2str(i)];
        else
            Style='o';
            MarkerSize=6;
            Color=[0 0 0];
            if ~isempty(Xi)
                Legends{end+1}='Noise';
            end
        end
        if ~isempty(Xi)
            plot(Xi(:,1),Xi(:,2),Style,'MarkerSize',MarkerSize,'Color',Color);
        end
        hold on;
    end
    hold off;
    axis equal;
    grid on;
    legend(Legends);
    legend('Location','NorthEastOutside');
end



function threshold = threshold_calculate( A )
numData=size(A,1);
M=1000;
ratio=0.007;
Kdist=zeros(M,1);
[IDX,Dist]=knnsearch(A(2:end,:),A(1,:));
Kdist(1)=Dist;
for i=2:M
    [IDX,Dist]=knnsearch(A([1:i-1,i+1:end],:),A(i,:));
    Kdist(i)=Dist;
end
[sortKdist,sortKdistIdx]=sort(Kdist,'descend');
threshold=sortKdist(round(M*ratio));

end


%主函数
clc;
clear;
theta=0:0.01:2*pi;
d1=[3*cos(theta)+rand(1,length(theta))/2;3*sin(theta)+rand(1,length(theta))/2];
d2=[2*cos(theta)+rand(1,length(theta))/2;2*sin(theta)+rand(1,length(theta))/2];
d3=[cos(theta)+rand(1,length(theta))/2;sin(theta)+rand(1,length(theta))/2];
d=[d1 d2 d3]';
randIndex=randperm(length(d))';
d=d(randIndex,:);
figure(1)
plot(d(:,1),d(:,2),'.');


%寻找最佳邻域半径epsilon,即下降最快处的值
A=d;
numData=size(A,1);
Kdist=zeros(numData,1);
[IDX,Dist]=knnsearch(A(2:numData,:),A(1,:));
Kdist(1)=Dist;
for i=2:size(A,1)
    [IDX,Dist] = knnsearch(A([1:i-1,i+1:numData],:),A(i,:));
    Kdist(i)=Dist;
end
[sortKdist,sortKdistIdx]=sort(Kdist,'descend');
distX=[1:numData]';
figure(2)
plot(distX,sortKdist,'r+-','LineWidth',2);
set(gcf,'position',[1000 340 350 350]);
grid on;



%epsilon=threshold_calculate(d);
epsilon=0.25;
MinPts=5;
IDX1=DBS(d,epsilon,MinPts);
figure(3)
plotClusterinResult(d,IDX1);

 

 

 

你可能感兴趣的:(聚类算法)