DBSCAN聚类学习-matlab代码撰写-2022-08-10

对于dbscan的学习,来自于以下的博主,非常的感谢

DBSCAN详解_皮卡丘的情绪的博客-CSDN博客_dbscan

所以,博主再这里不阐述dbscan的原理了,直接上代码,所有注释都有,可以直接吃和改进:

1 dbscan在matlab中的实现

% dbscan学习
% 模拟数据
clc
clear
rng('default') % For reproducibility

% Parameters for data generation
N = 300;  % Size of each cluster
r1 = 0.5; % Radius of first circle
r2 = 5;   % Radius of second circle
theta = linspace(0,2*pi,N)';

X1 = r1*[cos(theta),sin(theta)]+ rand(N,1);
X2 = r2*[cos(theta),sin(theta)]+ rand(N,1);
data = [X1;X2]; % Noisy 2-D circular data set
scatter(data(:,1),data(:,2))
title('聚类之前')

% 设置参数,esp为领域大小,minpt为最小数量点
esp = 1;
minpt = 5;

% 计算点与点之间的距离,三维点同样适用
% pdist2(a,b),计算a中的点到b中的点的距离
% 第一行为a中第一个点到b中所有点的距离
% d = pdist2(data,data);
% Rgion = find(d(1,:)<=esp); 0 % rangesearch功能为搜索esp内的所有点 d="rangesearch(data,data,esp);" 计算数据的大小 [n,m]="size(data);" 设置访问标记 vist="zeros(n,1);" 设置聚类组 idx="zeros(n,1);" 设置聚类标签 lab="0;" 循环整个点组 for i="1:n" 是否第i个点已经被访问过,如果被访问过,就下一个点 如果没有被访问过,则继续处理 if vist(i,:)="=" 访问设置为1,没被访问为0 提取集合 neig="d{i};" 判断是否满足阈值条件,即是否可以聚类 numel(neig)>=minpt
            % &#x5982;&#x679C;&#x5BC6;&#x5EA6;&#x53EF;&#x4EE5;&#x805A;&#x7C7B;&#xFF0C;&#x521B;&#x5EFA;&#x7C7B;&#x7684;&#x6807;&#x7B7E;
            lab = lab+1;
            % &#x4E3A;&#x5F53;&#x524D;&#x70B9;&#x5F52;&#x7C7B;
            idx(i,:) = lab;
            % &#x8BBE;&#x7F6E;&#x5FAA;&#x73AF;&#x6307;&#x9488;
            k = 1;

            % &#x8FDB;&#x884C;&#x5BC6;&#x5EA6;&#x53EF;&#x8FBE;&#x5BFB;&#x627E;
            while neig
                % &#x5BFB;&#x627E;d&#x96C6;&#x5408;&#x4E2D;&#x7B2C;i&#x4E2A;&#x70B9;&#x7684;esp&#x90BB;&#x57DF;&#x7684;&#x7B2C;k&#x4E2A;&#x70B9;
                j = neig(k);

                % &#x5224;&#x65AD;&#x5F53;&#x524D;&#x70B9;&#x662F;&#x5426;&#x88AB;&#x8BBF;&#x95EE;&#x8FC7;
                if  vist(j,:) == 0
                    % &#x5982;&#x679C;&#x6CA1;&#x88AB;&#x8BBF;&#x95EE;&#xFF0C;&#x5219;&#x8BBE;&#x7F6E;&#x4E3A;1&#xFF0C;&#x5373;&#x8BBF;&#x95EE;&#x8FC7;
                    vist(j,:) = 1;
                    % &#x63D0;&#x53D6;&#x65B0;&#x7684;&#x96C6;&#x5408;
                    neig2 = d{j};

                    % &#x5224;&#x65AD;&#x5F53;&#x524D;&#x70B9;&#x7684;&#x9886;&#x57DF;&#x70B9;&#x6570;&#x91CF;&#x662F;&#x5426;&#x6EE1;&#x8DB3;&#x6761;&#x4EF6;
                    if numel(neig2)>=minpt
                        % &#x6EE1;&#x8DB3;&#x6761;&#x4EF6;&#xFF0C;&#x5373;&#x5C06;&#x5F53;&#x524D;&#x70B9;&#x7684;&#x6240;&#x6709;&#x90BB;&#x57DF;&#x70B9;&#x7EB3;&#x5165;&#x7B2C;i&#x70B9;&#x96C6;&#x5408;
                        neig = [neig,neig2];
                        neig = unique(neig);
                    end
                else
                    neig(k) =[];
                end

                % &#x5982;&#x679C;&#x7B2C;j&#x4E2A;&#x70B9;&#x6CA1;&#x6709;&#x4ECE;&#x5C5E;&#x7C7B;&#xFF0C;&#x5219;&#x5F52;&#x7C7B;
                if idx(j,:) == 0
                    idx(j) = lab;
                end

                % &#x6307;&#x9488;&#x5F80;&#x524D;&#xFF0C;&#x5982;&#x679C;&#x6307;&#x9488;&#x7684;&#x503C;&#x5927;&#x4E8E;neig&#x96C6;&#x5408;&#x7684;&#x70B9;&#x7684;&#x4E2A;&#x6570;
                % &#x8BF4;&#x660E;&#x6CA1;&#x6709;&#x5BC6;&#x5EA6;&#x53EF;&#x8FBE;&#x7684;&#x70B9;&#xFF0C;&#x5219;&#x7ED3;&#x675F;&#x5FAA;&#x73AF;
                % k = k+1;
                % if k > numel(neig)
                %   break
                % end
            end

        end

    end
end

gscatter(data(:,1),data(:,2),idx);
title('&#x805A;&#x7C7B;&#x4E4B;&#x540E;')
</=esp);>

结果如下:

DBSCAN聚类学习-matlab代码撰写-2022-08-10

DBSCAN聚类学习-matlab代码撰写-2022-08-10

自写得dbscan运行很慢,比起matlab自带得功能,慢上十倍,2w数量的点云分割,需要1分钟。

不知道问题出在哪里,已经看了很多博主写的代码了,仍然没有解决,痛苦。

2 matlab自带dbscan的功能

matlab2019b自带dbscan函数,应用如下:

<a href="https://localhost:31515/static/help/stats/dbscan.html?searchHighlight=dbscan&searchResultIndex=1#d117e261580" title="idx = dbscan(X,epsilon,minpts)">idx =&#xA0;dbscan(X,epsilon,minpts)</a> <a href="https://localhost:31515/static/help/stats/dbscan.html?searchHighlight=dbscan&searchResultIndex=1#d117e261632" title="idx = dbscan(X,epsilon,minpts,Name,Value)">idx =&#xA0;dbscan(X,epsilon,minpts,Name,Value)</a> <a href="https://localhost:31515/static/help/stats/dbscan.html?searchHighlight=dbscan&searchResultIndex=1#d117e261664" title="idx = dbscan(D,epsilon,minpts,'Distance','precomputed')">idx =&#xA0;dbscan(D,epsilon,minpts,'Distance','precomputed')</a> <a href="https://localhost:31515/static/help/stats/dbscan.html?searchHighlight=dbscan&searchResultIndex=1#d117e261712" title="[idx,corepts] = dbscan(___)">[idx,corepts] =&#xA0;dbscan(___)</a>

DBSCAN聚类学习-matlab代码撰写-2022-08-10
clc
clear
rng('default') % For reproducibility

% Parameters for data generation
N = 300;  % Size of each cluster
r1 = 0.5; % Radius of first circle
r2 = 5;   % Radius of second circle
theta = linspace(0,2*pi,N)';

X1 = r1*[cos(theta),sin(theta)]+ rand(N,1);
X2 = r2*[cos(theta),sin(theta)]+ rand(N,1);
data = [X1;X2]; % Noisy 2-D circular data set
scatter(data(:,1),data(:,2))
title('&#x805A;&#x7C7B;&#x4E4B;&#x524D;')
axis on

idx = dbscan(data,1,5);
gscatter(data(:,1),data(:,2),idx);
title('&#x805A;&#x7C7B;&#x4E4B;&#x540E;')

结果如下:

DBSCAN聚类学习-matlab代码撰写-2022-08-10

DBSCAN聚类学习-matlab代码撰写-2022-08-10

效果的差异不明显

此外博主写的k均值和欧式距离聚类如下:

Kmean(k均值聚类)学习-2022-08-09_~追风筝的猫的博客-CSDN博客

Matlab点云欧式距离聚类-2021-12-06_~追风筝的猫的博客-CSDN博客_matlab 欧式聚类

点云-均值漂移-均适用_点云均值漂移-数据集文档类资源-CSDN下载

3、 8月11更新,dbscan代码小优化,运行速度提升

借鉴于以下博主:

DBSCAN的理解和matlab实现_尼古拉斯.贝叶斯基的博客-CSDN博客_dbscan matlab

修改了密度可达的集合合并,比之前的运行速度快了十倍,但是比起matlab自带的函数还是慢着很多很多,不过已经很好了,感觉基本得到了解决。不列结果了,基本一样

clc
clear
rng('default') % For reproducibility

% Parameters for data generation
N = 300;  % Size of each cluster
r1 = 0.5; % Radius of first circle
r2 = 5;   % Radius of second circle
theta = linspace(0,2*pi,N)';

X1 = r1*[cos(theta),sin(theta)]+ rand(N,1);
X2 = r2*[cos(theta),sin(theta)]+ rand(N,1);
data = [X1;X2]; % Noisy 2-D circular data set
scatter(data(:,1),data(:,2))

% clear
% clc
% % &#x6A21;&#x62DF;&#x6570;&#x636E;
% [X,Y,Z] = sphere(100);
% loc1 = [X(:),Y(:),Z(:)];
% loc2 = 2*loc1;
% ptCloud = pointCloud([loc1;loc2]);
% pcshow(ptCloud)
% title('Point Cloud')
% data = ptCloud.Location;

tic
% &#x8BBE;&#x7F6E;&#x53C2;&#x6570;&#xFF0C;esp&#x4E3A;&#x9886;&#x57DF;&#x5927;&#x5C0F;&#xFF0C;minpt&#x4E3A;&#x6700;&#x5C0F;&#x6570;&#x91CF;&#x70B9;
esp = 1;
minpt = 5;

% &#x8BA1;&#x7B97;&#x70B9;&#x4E0E;&#x70B9;&#x4E4B;&#x95F4;&#x7684;&#x8DDD;&#x79BB;,&#x4E09;&#x7EF4;&#x70B9;&#x540C;&#x6837;&#x9002;&#x7528;
% pdist2(a,b)&#xFF0C;&#x8BA1;&#x7B97;a&#x4E2D;&#x7684;&#x70B9;&#x5230;b&#x4E2D;&#x7684;&#x70B9;&#x7684;&#x8DDD;&#x79BB;
% &#x7B2C;&#x4E00;&#x884C;&#x4E3A;a&#x4E2D;&#x7B2C;&#x4E00;&#x4E2A;&#x70B9;&#x5230;b&#x4E2D;&#x6240;&#x6709;&#x70B9;&#x7684;&#x8DDD;&#x79BB;
% d = pdist2(data,data);
% Rgion = find(d(1,:)<=esp); 0 % rangesearch功能为搜索esp内的所有点 d="rangesearch(data,data,esp);" 计算数据的大小 [n,m]="size(data);" 设置访问标记 vist="zeros(n,1);" 设置聚类组 idx="zeros(n,1);" 设置聚类标签 lab="0;" 循环整个点组 for i="1:n" 是否第i个点已经被访问过,如果被访问过,就下一个点 如果没有被访问过,则继续处理 if vist(i,:)="=" 访问设置为1,没被访问为0 提取集合 neig="d{i};" 判断是否满足阈值条件,即是否可以聚类 numel(neig)>=minpt
            % &#x5982;&#x679C;&#x5BC6;&#x5EA6;&#x53EF;&#x4EE5;&#x805A;&#x7C7B;&#xFF0C;&#x521B;&#x5EFA;&#x7C7B;&#x7684;&#x6807;&#x7B7E;
            lab = lab+1;
            % &#x4E3A;&#x5F53;&#x524D;&#x70B9;&#x5F52;&#x7C7B;
            idx(i,:) = lab;
            % &#x8BBE;&#x7F6E;&#x5FAA;&#x73AF;&#x6307;&#x9488;
            k = 1;

            % &#x8FDB;&#x884C;&#x5BC6;&#x5EA6;&#x53EF;&#x8FBE;&#x5BFB;&#x627E;
            while true
                % &#x5BFB;&#x627E;d&#x96C6;&#x5408;&#x4E2D;&#x7B2C;i&#x4E2A;&#x70B9;&#x7684;esp&#x90BB;&#x57DF;&#x7684;&#x7B2C;k&#x4E2A;&#x70B9;
                j = neig(k);

                % &#x5224;&#x65AD;&#x5F53;&#x524D;&#x70B9;&#x662F;&#x5426;&#x88AB;&#x8BBF;&#x95EE;&#x8FC7;
                if  vist(j,:) == 0
                    % &#x5982;&#x679C;&#x6CA1;&#x88AB;&#x8BBF;&#x95EE;&#xFF0C;&#x5219;&#x8BBE;&#x7F6E;&#x4E3A;1&#xFF0C;&#x5373;&#x8BBF;&#x95EE;&#x8FC7;
                    vist(j,:) = 1;
                    % &#x63D0;&#x53D6;&#x65B0;&#x7684;&#x96C6;&#x5408;
                    neig2 = d{j};

                    % &#x5224;&#x65AD;&#x5F53;&#x524D;&#x70B9;&#x7684;&#x9886;&#x57DF;&#x70B9;&#x6570;&#x91CF;&#x662F;&#x5426;&#x6EE1;&#x8DB3;&#x6761;&#x4EF6;
                    if numel(neig2)>=minpt
                        % &#x6EE1;&#x8DB3;&#x6761;&#x4EF6;&#xFF0C;&#x5373;&#x5C06;&#x5F53;&#x524D;&#x70B9;&#x7684;&#x6240;&#x6709;&#x90BB;&#x57DF;&#x70B9;&#x7EB3;&#x5165;&#x7B2C;i&#x70B9;&#x96C6;&#x5408;
                        neig2 = setdiff(neig2,neig);
                        neig = [neig,neig2];
                    end
              % else
                   % neig(k) =[];
                end

                % &#x5982;&#x679C;&#x7B2C;j&#x4E2A;&#x70B9;&#x6CA1;&#x6709;&#x4ECE;&#x5C5E;&#x7C7B;&#xFF0C;&#x5219;&#x5F52;&#x7C7B;
                if idx(j,:) == 0
                    idx(j) = lab;
                end

                % &#x6307;&#x9488;&#x5F80;&#x524D;&#xFF0C;&#x5982;&#x679C;&#x6307;&#x9488;&#x7684;&#x503C;&#x5927;&#x4E8E;neig&#x96C6;&#x5408;&#x7684;&#x70B9;&#x7684;&#x4E2A;&#x6570;
                % &#x8BF4;&#x660E;&#x6CA1;&#x6709;&#x5BC6;&#x5EA6;&#x53EF;&#x8FBE;&#x7684;&#x70B9;&#xFF0C;&#x5219;&#x7ED3;&#x675F;&#x5FAA;&#x73AF;
                k = k+1;
                if k > numel(neig)
                  break
                end
            end

        end

    end
end

toc

% pcshow(data,idx)
gscatter(data(:,1),data(:,2),idx);
</=esp);>

Original: https://blog.csdn.net/qq_39632121/article/details/126261935
Author: ~追风筝的猫
Title: DBSCAN聚类学习-matlab代码撰写-2022-08-10

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/560222/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球