设为首页收藏本站

EPS数据狗论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1527|回复: 0

matlab练习程序(DBSCAN)

[复制链接]

35

主题

369

金钱

516

积分

初级用户

发表于 2019-7-24 16:18:34 | 显示全部楼层 |阅读模式

DBSCAN全称Density-Based Spatial Clustering of Applications with Noise,是一种密度聚类算法。

和Kmeans相比,不需要事先知道数据的类数。
以编程的角度来考虑,具体算法流程如下:
1.首先选择一个待处理数据。
2.寻找和待处理数据距离在设置半径内的数据。
3.将找到的半径内的数据放到一个队列中。
4.拿队列头数据作为当前待处理数据并不断执行第2步。
5.直到遍历完队列中所有数据,将这些数据记为一类。
6.选择没有处理到的数据作为一个待处理数据执行第2步。
7.直到遍历完所有数据,算法结束。
大概就是下图所示的样子:
1.png


我这里没有单独输出离群点,不过稍微改进增加离群点个数判断阈值应该就可以,比较容易修改。
代码如下:
  1. clear all;
  2. close all;
  3. clc;

  4. K=3;
  5. theta=0:0.01:2*pi;
  6. p1=[3*cos(theta) + rand(1,length(theta))/2;3*sin(theta)+ rand(1,length(theta))/2];      %生成测试数据
  7. p2=[2*cos(theta) + rand(1,length(theta))/2;2*sin(theta)+ rand(1,length(theta))/2];
  8. p3=[cos(theta) + rand(1,length(theta))/2;sin(theta)+ rand(1,length(theta))/2];
  9. p=[p1 p2 p3]';

  10. randIndex = randperm(length(p))';       %打乱数据顺序
  11. p=p(randIndex,:);
  12. plot(p(:,1),p(:,2),'.')

  13. flag = zeros(length(p),1);      %聚类标记
  14. clsnum = 0;                     %类的个数
  15. disnear = 0.3;                 %聚类半径

  16. for i=1:length(p)   
  17.     nxtp = p(i,:);      %初始聚类半径内的邻域点队列
  18.     if flag(i)==0
  19.         clsnum = clsnum+1;
  20.         pcstart = 1;            %设置队列起始指针
  21.         preflag = flag;         %聚类标记更新
  22.         while pcstart<=length(nxtp)         %判断是否完成队列遍历
  23.             curp = nxtp(pcstart,:);         %得到当前要处理的点
  24.             pcstart = pcstart+1;            %队列指针更新
  25.             diffp = p-curp;                 %这里直接和所有数据比较了,数据量大的时候可以考虑kdtree
  26.             dis = sqrt(diffp(:,1).*diffp(:,1)+diffp(:,2).*diffp(:,2));      %判断当前点与所有点之间的距离        

  27.             ind = dis<disnear;                  %得到距离小于阈值的索引
  28.             flag(ind) = clsnum;                 %设置当前聚类标记
  29.             
  30.             diff_flag = preflag-flag;   
  31.             diff_ind = (preflag-flag)<0;        %判断本次循环相比上次循环增加的点
  32.             
  33.             tmp = zeros(length(p),1);
  34.             tmp(diff_ind) = clsnum;
  35.             flag = flag + tmp;                  %增加的点将其标记为一类
  36.             preflag = flag;                 %聚类标记更新
  37.             nxtp = [nxtp;p(diff_ind,:)];    %增加聚类半径内的邻域点队列
  38.         end      
  39.     end   
  40. end

  41. %聚类可能不止三组,我偷懒不想判断并plot了
  42. figure;
  43. plot(p(flag==1,1),p(flag==1,2),'r.')
  44. hold on;
  45. plot(p(flag==2,1),p(flag==2,2),'g.')   
  46. plot(p(flag==3,1),p(flag==3,2),'b.')
复制代码


结果如下:
原始数据:
2.png
聚类结果:
3.png

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

客服中心
关闭
在线时间:
周一~周五
8:30-17:30
QQ群:
653541906
联系电话:
010-85786021-8017
在线咨询
客服中心

意见反馈|网站地图|手机版|小黑屋|EPS数据狗论坛 ( 京ICP备09019565号-3 )   

Powered by BFIT! X3.4

© 2008-2028 BFIT Inc.

快速回复 返回顶部 返回列表