数学建模——聚类算法matlab

一、应用

对未知类别的对象进行分类,可以更加准确的在每个类中单独使用统计模型进行估计、分析或预测;也可以探究不同类之间的相关性和差异性。

①图像处理

->分割:图像像素划分为不同的簇,便于提取目标物体和区域

->压缩:相似像素归为一类,减少颜色数量,实现图像压缩

②分类

->划分客户群体,市场分析

->对基因表达数据进行聚类,以发现具有相似表达模式的基因群,以及蛋白质结构分类

->文档聚类

二、KMeans

1、流程图

2、算法流程(Kmeans++)

->随机选取样本作为第一个聚类中心

->计算每个样本与当前已有聚类中心的最短距离(值越大,该样本被选为聚类中心的概率越大)

->轮盘法(依据概率大小抽选)选出下一个聚类中心

->重复2、3,直到选出k个聚类中心

3、matlab实现

% Step 1: 加载数据
load mydata  %data会创建两个变量meas和species
data = meas;

% Step 2: 标准化数据
%option:提取感兴趣的特征列
data = data(:, [1, 3]);
data = zscore(data);

% 确定簇的数量 K
SSE = [];
silhouetteScores = [];
for k = 2:10
    %迭代100次,重复运行10次
    [idx, ~, sumd] = kmeans(data, k, 'MaxIter', 100, 'Replicates', 10, 'TolFun', 1e-4);
    SSE = [SSE; sum(sumd)];
    %平均轮廓系数
    s = silhouette(data, idx);
    silhouetteScores = [silhouetteScores; mean(s)];
end

% 可视化肘部法和轮廓系数
figure;
subplot(1,2,1);
plot(2:10, SSE, '-o');
xlabel('簇的数量 K');
ylabel('SSE');
title('肘部法选择 K 值');

subplot(1,2,2);
plot(2:10, silhouetteScores, '-o');
xlabel('簇的数量 K');
ylabel('平均轮廓系数');
title('轮廓系数选择 K 值');

% 选择合适的 K 值
K = 3; 

% 运行 K-means 算法
maxIter = 100; % 根据经验设定最大迭代次数
tol = 1e-4; % 根据数据特征设定收敛容限
[idx, C] = kmeans(data, K, 'MaxIter', maxIter, 'Replicates', 10, 'Display', 'final', 'TolFun', tol);

% 结果可视化
figure;
gscatter(data(:,1), data(:,2), idx, 'rbg', 'o');
hold on;
plot(C(:,1), C(:,2), 'kx', 'MarkerSize', 10, 'LineWidth', 3);
title('K-means 聚类结果');
xlabel('特征 1');
ylabel('特征 2');
legend('簇 1', '簇 2', '簇 3', '质心', 'Location', 'Best');
hold off;

5、补充(matlab读入数据集的方式)

(1)文件导入

①读入xlsx

filename = '文件路径';
sheet = 1; % 工作表编号或名称
range = 'A1:D150'; % 数据范围(可选)

data = readtable(filename, 'Sheet', sheet, 'Range', range);

②读入csv

filename = 'data.csv';
data = readtable(filename);

③ 读入txt

filename = 'data.txt';
data = readtable(filename, 'Delimiter', '\t'); % 指定列分隔符

(2).mat导入

filename = 'data.mat';
load(filename);
% 这将加载 .mat 文件中的所有变量到工作区

三、层次(系统)聚类

1、流程图

2、matlab实现

% 清空变量
warning off             % 关闭报警信息
close all               % 关闭开启的图窗
clear                   % 清空变量
clc                     % 清空命令行

% 读取数据
% 选取想要的列
data = readtable('iris.xlsx');
X = table2array(data(:, 1:4));

% 调用层次聚类函数
Z = linkage(X, 'single');
% 'single'单连接(single linkage)
% 'complete'完全连接(complete linkage)
% 'average'平均连接(average linkage)
% 'weighted'加权连接(weighted linkage)
% 'centroid'中心连接(centroid linkage)

% 绘制聚类树状图
dendrogram(Z)
title('Dendrogram of Iris Dataset')
xlabel('Samples')
ylabel('Distance')

四、DBSCAN

1、基本原理

基于密度的聚类方法,聚类前不用预先指定聚类的个数。可以发现任意形状的簇,可以将密度足够大的相邻区域连接,有效处理异常数据。简单来说,其目的就是找到密度相连对象的最大集合。

2、概念

①核心对象:领域内样本点数>=阈值

②直接密度可达

③密度可达

④密度相连

3、MATLAB

(1)DBSCAN.m

function [IDX, isnoise]=DBSCAN(X,epsilon,MinPts)    % DBSCAN聚类函数
 
    C=0;                       % 统计簇类个数,初始化为0
    
    n=size(X,1);               % 把矩阵X的行数数赋值给n,即一共有n个点
    IDX=zeros(n,1);            % 定义一个n行1列的矩阵
    
    D=pdist2(X,X);             % 计算(X,X)的行的距离
    
    visited=false(n,1);        % 创建一维的标记数组,全部初始化为false,代表还未被访问
    isnoise=false(n,1);        % 创建一维的异常点数组,全部初始化为false,代表该点不是异常点
    
    for i=1:n                  % 遍历1~n个所有的点
        if ~visited(i)         % 未被访问,则执行下列代码
            visited(i)=true;   % 标记为true,已经访问
            
            Neighbors=RegionQuery(i);     % 查询周围点中距离小于等于epsilon的个数
            if numel(Neighbors)<MinPts    % 如果小于MinPts
                % X(i,:) is NOISE        
                isnoise(i)=true;          % 该点是异常点
            else              % 如果大于MinPts,且距离大于epsilon
                C=C+1;        % 该点又是新的簇类中心点,簇类个数+1
                ExpandCluster(i,Neighbors,C);    % 如果是新的簇类中心,执行下面的函数
            end
            
        end
    
    end                    % 循环完n个点,跳出循环
    
    function ExpandCluster(i,Neighbors,C)    % 判断该点周围的点是否直接密度可达
        IDX(i)=C;                            % 将第i个C簇类记录到IDX(i)中
        
        k = 1;                             
        while true                           % 一直循环
            j = Neighbors(k);                % 找到距离小于epsilon的第一个直接密度可达点
            
            if ~visited(j)                   % 如果没有被访问
                visited(j)=true;             % 标记为已访问
                Neighbors2=RegionQuery(j);   % 查询周围点中距离小于epsilon的个数
                if numel(Neighbors2)>=MinPts % 如果周围点的个数大于等于Minpts,代表该点直接密度可达
                    Neighbors=[Neighbors Neighbors2];   %#ok  % 将该点包含着同一个簇类当中
                end
            end                              % 退出循环
            if IDX(j)==0                     % 如果还没形成任何簇类
                IDX(j)=C;                    % 将第j个簇类记录到IDX(j)中
            end                              % 退出循坏
            
            k = k + 1;                       % k+1,继续遍历下一个直接密度可达的点
            if k > numel(Neighbors)          % 如果已经遍历完所有直接密度可达的点,则退出循环
                break;
            end
        end
    end                                      % 退出循环
    
    function Neighbors=RegionQuery(i)        % 该函数用来查询周围点中距离小于等于epsilon的个数
        Neighbors=find(D(i,:)<=epsilon);
    end
 
end

(2)PlotClusterinResult.m


function PlotClusterinResult(X, IDX)                % 绘图,标绘聚类结果
 
    k=max(IDX);                                     % 求矩阵IDX每一列的最大元素及其对应的索引
 
    Colors=hsv(k);                                  % 颜色设置
 
    Legends = {};
    for i=0:k                                       % 循环每一个簇类
        Xi=X(IDX==i,:);                    
        if i~=0                                     
            Style = 'x';                            % 标记符号为x
            MarkerSize = 8;                         % 标记尺寸为8
            Color = Colors(i,:);                    % 所有点改变颜色改变
            Legends{end+1} = ['Cluster #' num2str(i)]; 
        else
            Style = 'o';                            % 标记符号为o
            MarkerSize = 6;                         % 标记尺寸为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');      % legend默认的位置在NorthEast,将其设置在外侧
 
end                                              % 结束循环  

(3)main.m


clc;                    %清理命令行的意思
clear;                  %清楚存储空间的变量,以免对下面的程序运行产生影响
close all;              %关闭所有图形窗口
 
%% Load Data            %定义data.mat数据文件加载模块
 
data=load('mydata');    %数据读取
X=data.X;
 
 
%% Run DBSCAN Clustering Algorithm    %定义Run运行模块
 
epsilon=0.5;                          %规定两个关键参数的取值
MinPts=10;
IDX=DBSCAN(X,epsilon,MinPts);         %传入参数运行
 
 
%% Plot Results                       %定义绘图结果模块
 
PlotClusterinResult(X, IDX);          %传入参数,绘制图像
title(['DBSCAN Clustering (\epsilon = ' num2str(epsilon) ', MinPts = ' num2str(MinPts) ')']);

五、算法选择

只有两个指标,且做出散点图后发现数据表现得很“DBSCAN”(簇的形状是任意的),这时候再用DBSCAN进行聚类。其他情况下,全部使用系统聚类吧。K‐means也可以用,不过用了的话论文上可写的东西比较少。

参考资料

1、【11】 数学建模 | 聚类模型 | K-means++算法、系统聚类算法_数模算法流程图-CSDN博客

2、 Matlab实现DBSCAN算法(每行代码标注详细注解)_matlab dbscan-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值