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