matlab練習程序(DBSCAN)

DBSCAN全稱Density-Based Spatial Clustering of Applications with Noise,是一種密度聚類算法。算法

和Kmeans相比,不須要事先知道數據的類數。編程

以編程的角度來考慮,具體算法流程以下:測試

1.首先選擇一個待處理數據。spa

2.尋找和待處理數據距離在設置半徑內的數據。指針

3.將找到的半徑內的數據放到一個隊列中。code

4.拿隊列頭數據做爲當前待處理數據並不斷執行第2步。blog

5.直到遍歷完隊列中全部數據,將這些數據記爲一類。索引

6.選擇沒有處理到的數據做爲一個待處理數據執行第2步。隊列

7.直到遍歷完全部數據,算法結束。it

大概就是下圖所示的樣子:

我這裏沒有單獨輸出離羣點,不過稍微改進增長離羣點個數判斷閾值應該就能夠,比較容易修改。

代碼以下:

clear all;
close all;
clc;

theta=0:0.01:2*pi;
p1=[3*cos(theta) + rand(1,length(theta))/2;3*sin(theta)+ rand(1,length(theta))/2];      %生成測試數據
p2=[2*cos(theta) + rand(1,length(theta))/2;2*sin(theta)+ rand(1,length(theta))/2];
p3=[cos(theta) + rand(1,length(theta))/2;sin(theta)+ rand(1,length(theta))/2];
p=[p1 p2 p3]';

randIndex = randperm(length(p))';       %打亂數據順序
p=p(randIndex,:);
plot(p(:,1),p(:,2),'.')

flag = zeros(length(p),1);      %聚類標記
clsnum = 0;                     %類的個數
disnear = 0.3;                 %聚類半徑

for i=1:length(p)   
    nxtp = p(i,:);      %初始聚類半徑內的鄰域點隊列
    if flag(i)==0
        clsnum = clsnum+1;
        pcstart = 1;            %設置隊列起始指針
        preflag = flag;         %聚類標記更新
        while pcstart<=length(nxtp)         %判斷是否完成隊列遍歷
            curp = nxtp(pcstart,:);         %獲得當前要處理的點
            pcstart = pcstart+1;            %隊列指針更新
            diffp = p-curp;                 %這裏直接和全部數據比較了,數據量大的時候能夠考慮kdtree
            dis = sqrt(diffp(:,1).*diffp(:,1)+diffp(:,2).*diffp(:,2));      %判斷當前點與全部點之間的距離        

            ind = dis<disnear;                  %獲得距離小於閾值的索引
            flag(ind) = clsnum;                 %設置當前聚類標記
            
            diff_flag = preflag-flag;   
            diff_ind = (preflag-flag)<0;        %判斷本次循環相比上次循環增長的點
            
            tmp = zeros(length(p),1);
            tmp(diff_ind) = clsnum;
            flag = flag + tmp;                  %增長的點將其標記爲一類
            preflag = flag;                 %聚類標記更新
            nxtp = [nxtp;p(diff_ind,:)];    %增長聚類半徑內的鄰域點隊列
        end       
    end    
end

%聚類可能不止三組,我偷懶不想判斷並plot了 figure; plot(p(flag
==1,1),p(flag==1,2),'r.') hold on; plot(p(flag==2,1),p(flag==2,2),'g.') plot(p(flag==3,1),p(flag==3,2),'b.')

結果以下:

原始數據:

聚類結果:

相關文章
相關標籤/搜索