Matlab实现AGNES算法(每行代码标注详细注解)

在数据分析和机器学习中,聚类是一种常用的无监督学习方法,它可以将数据点按照某种相似度标准进行分组,从而发现数据中的结构和模式。聚类算法有很多种,其中一种比较经典的是AGNES算法,它是一种基于层次的聚类算法,它的全称是Agglomerative Nesting,即凝聚式嵌套。在这篇博客中,我将介绍AGNES算法的原理和意义,并给出一个用Matlab实现的代码示例。

目录

一、什么是AGNES算法

二、AGNES算法的意义

1.AGNES算法的优点

2.AGNES算法的应用场景

三、如何实现AGNES算法

1.AGNES算法大致思路

2.Matlab实现AGNES算法,对照每行代码标注详细注解

四、AGNES算法的总结和建议

这里是希望和大家一起进步的小高,愿意和读者们热情探讨😊


一、什么是AGNES算法

AGNES算法的原理是将数据集中的对象看作是一个图(graph)中的节点(node),然后根据节点之间的距离或者相似度来构建一个邻接矩阵(adjacency matrix)。邻接矩阵表示了图中节点之间是否相连以及相连程度。然后通过使用不同的连接方式(linkage)来计算不同簇之间的距离或者相似度,并且将最近或者最相似的两个簇合并成一个新的簇。这个过程重复进行,直到所有的节点都合并成一个大的簇为止。最后,根据需要划分的簇的个数,从合并过程中产生的树形结构(dendrogram)中切断一条水平线,得到最终的簇划分。

二、AGNES算法的意义

1.AGNES算法的优点

  • 不需要预先指定簇的个数,可以自动发现合适的簇的个数。
  • 可以生成一个树形结构,表示数据点之间的层次关系,方便进行可视化和分析。
  • 可以使用不同的距离度量和链接方法,适应不同的数据特征和需求。

例如,如果我们想要对一些文本数据进行聚类,我们可以使用余弦相似度作为距离度量,并使用平均链接作为链接方法。

2.AGNES算法的应用场景

  • 数据挖掘:可以用于对大量数据进行分组和分类,发现数据中的潜在模式和规律。
  • 信息检索:可以用于对文档或网页进行聚类,提高检索效率和质量。
  • 生物信息学:可以用于对基因或蛋白质进行聚类,揭示生物系统的结构和功能。
  • 图像处理:可以用于对图像进行分割或压缩,提高图像质量和效果。

三、如何实现AGNES算法

1.AGNES算法大致思路

(1)构建邻接矩阵:给定一个数据集X,其中包含n个对象,每个对象有p个属性。首先计算每两个对象之间的距离或者相似度,然后根据一定的规则来构建一个n乘n的邻接矩阵A。常用的规则有以下几种:

  • K近邻法(KNN):对于每个对象,只与其最近的K个对象相连,即A[i,j]=1当且仅当对象i和j是彼此最近的K个对象之一,否则A[i,j]=0。
  • ε-邻域法(ε-neighborhood):对于每个对象,只与其距离小于ε的对象相连,即A[i,j]=1当且仅当对象i和j之间的距离小于ε,否则A[i,j]=0。
  • 全连接法(fully connected):对于每个对象,与所有其他对象相连,即A[i,j]等于对象i和j之间的距离或者相似度。

(2)选择连接方式:根据不同的连接方式来计算不同簇之间的距离或者相似度。常用的连接方式有以下几种:

  • 最小距离法(single linkage):使用两个簇中最近的两个对象之间的距离作为簇之间的距离。
  • 最大距离法(complete linkage):使用两个簇中最远的两个对象之间的距离作为簇之间的距离。
  • 平均距离法(average linkage):使用两个簇中所有对象之间的平均距离作为簇之间的距离。
  • 中心距离法(centroid linkage):使用两个簇中各自计算出来的中心点之间的距离作为簇之间的距离。

(3)合并最近或者最相似的两个簇:根据所选用的连接方式,找出邻接矩阵中最小或者最大的元素,并且将对应的两个簇合并成一个新的簇。同时更新邻接矩阵,删除被合并掉的两个簇的行和列,增加新的簇的行和列,计算新的簇与其他簇之间的距离或者相似度。

(4)重复上一步,直到所有的节点都合并成一个大的簇为止:每次合并后,邻接矩阵的维度减一,直到只剩下一个元素为止。在合并的过程中,记录下每次合并的两个簇的编号和距离或者相似度,以及新产生的簇的编号。这些信息可以用来绘制树形结构(dendrogram)。

(5)根据需要划分的簇的个数,从树形结构中切断一条水平线,得到最终的簇划分:根据树形结构中不同高度的水平线,可以得到不同个数的簇划分。一般来说,水平线越高,划分出来的簇越少,水平线越低,划分出来的簇越多。可以根据实际问题或者数据特点来选择合适的水平线位置。

2.Matlab实现AGNES算法,对照每行代码标注详细注解

% 生成一个包含两个月牙形簇的数据集,共有300个样本,每个样本有两个属性
X = [moon(150,10,50,10);moon(150,10,-50,-10)]; % 使用自定义函数moon生成月牙形数据
y = [ones(150,1);2*ones(150,1)]; % 生成真实的簇标签
scatter(X(:,1),X(:,2),[],y) % 绘制数据集的散点图,不同颜色表示真实的簇标签
title('True labels') % 添加标题

% 构建邻接矩阵,使用欧氏距离计算距离
n = size(X,1); % 获取样本数
A = zeros(n,n); % 初始化邻接矩阵
for i = 1:n % 遍历每一个样本
    for j = i+1:n % 遍历其他样本
        A(i,j) = norm(X(i,:)-X(j,:)); % 计算欧氏距离
        A(j,i) = A(i,j); % 由于距离是对称的,所以复制到对角位置
    end
end

% 选择连接方式,这里使用最小距离法(single linkage)
method = 'single';

% 初始化合并记录矩阵Z,它有n-1行和3列,每一行记录了一次合并操作
% 第一列和第二列是被合并掉的两个簇的编号,第三列是合并后产生的新簇的编号
Z = zeros(n-1,3);

% 初始化当前存在的簇编号向量C,它有n个元素,每个元素表示对应样本所属的簇编号
C = (1:n)';

% 初始化当前存在的簇数k,它等于样本数n
k = n;

% 合并最近或者最相似的两个簇,重复进行n-1次
for t = 1:n-1 % 遍历每一次合并操作
    
    % 根据所选用的连接方式,找出邻接矩阵中最小或者最大的元素,并且获取对应的两个簇编号i和j
    if strcmp(method,'single') % 如果是最小距离法
        [min_val,min_idx] = min(A(:)); % 找出邻接矩阵中的最小值和其索引
        [i,j] = ind2sub(size(A),min_idx); % 将索引转换为行列坐标,即两个簇编号
    elseif strcmp(method,'complete') % 如果是最大距离法
        [max_val,max_idx] = max(A(:)); % 找出邻接矩阵中的最大值和其索引
        [i,j] = ind2sub(size(A),max_idx); % 将索引转换为行列坐标,即两个簇编号
    elseif strcmp(method,'average') % 如果是平均距离法
        A_mean = mean(A,2); % 计算邻接矩阵每一行的平均值
        [min_val,min_idx] = min(A_mean); % 找出平均值中的最小值和其索引,即一个簇编号
        i = min_idx; % 将索引赋值给i
        A_row = A(i,:); % 获取邻接矩阵第i行
        A_row(i) = inf; % 将第i行第i列的元素设为无穷大,避免干扰
        [min_val,min_idx] = min(A_row); % 找出第i行中的最小值和其索引,即另一个簇编号
        j = min_idx; % 将索引赋值给j
    elseif strcmp(method,'centroid') % 如果是中心距离法
        X_mean = mean(X,1); % 计算数据集每一列的平均值,即所有对象的中心点
        X_dist = pdist2(X,X_mean); % 计算每个对象与中心点的距离
        X_dist = X_dist ./ sum(X_dist); % 归一化距离,使其和为1
        A_centroid = A .* X_dist; % 计算邻接矩阵与距离的加权乘积,即每个元素乘以对应对象与中心点的距离比例
        A_centroid_mean = mean(A_centroid,2); % 计算加权邻接矩阵每一行的平均值
        [min_val,min_idx] = min(A_centroid_mean); % 找出平均值中的最小值和其索引,即一个簇编号
        i = min_idx; % 将索引赋值给i
        A_centroid_row = A_centroid(i,:); % 获取加权邻接矩阵第i行
        A_centroid_row(i) = inf; % 将第i行第i列的元素设为无穷大,避免干扰
        [min_val,min_idx] = min(A_centroid_row); % 找出第i行中的最小值和其索引,即另一个簇编号
        j = min_idx; % 将索引赋值给j
    end
    
    % 将对应的两个簇合并成一个新的簇,并且更新邻接矩阵,删除被合并掉的两个簇的行和列,增加新的簇的行和列,计算新的簇与其他簇之间的距离或者相似度
    C(C==j) = i; % 将编号为j的簇的所有对象的簇编号改为i,即将簇j合并到簇i中
    A(i,:) = min(A(i,:),A(j,:)); % 将邻接矩阵第i行和第j行取最小值,即使用最小距离法更新簇i与其他簇之间的距离
    A(:,i) = A(i,:)'; % 将邻接矩阵第i列设为第i行的转置,即保持对称性
    A(j,:) = []; % 删除邻接矩阵第j行
    A(:,j) = []; % 删除邻接矩阵第j列
    
    % 记录合并操作的信息,更新合并记录矩阵Z
    Z(t,1) = i; % 记录被合并掉的第一个簇的编号
    Z(t,2) = j; % 记录被合并掉的第二个簇的编号
    Z(t,3) = k+1; % 记录合并后产生的新簇的编号,从n+1开始递增
    k = k+1; % 更新当前存在的簇数,每次合并后加一
    
end

% 根据需要划分的簇的个数,从树形结构中切断一条水平线,得到最终的簇划分
n_clusters = 2; % 指定需要划分的簇的个数
T = clusterdata(X,'maxclust',n_clusters,'linkage',method); % 使用matlab自带的clusterdata函数进行层次聚类,指定最大簇数和连接方式,得到每个对象所属的簇编号
scatter(X(:,1),X(:,2),[],T) % 绘制聚类结果的散点图,不同颜色表示预测的簇标签
title('AGNES clustering') % 添加标题

% 计算AGNES聚类的调整兰德指数(Adjusted Rand Index),用于评估聚类效果,取值范围是[-1,1],越接近1表示越好
ari_agnes = adjusted_rand_score(y, T);
fprintf('ARI of AGNES: %.4f\n',ari_agnes);

补充:自定义函数moon

function data = moon(num, radius, offset, noise)
% MOON 生成一个月牙形状的数据簇
%   data = moon(num, radius, offset, noise) 返回一个N乘2的矩阵,其中
%   N是样本数,每一行表示一个点的x坐标和y坐标。这些点是从一个月牙形状的分布中生成的,
%   根据给定的半径、偏移量和噪声水平。

% 从0到pi均匀地生成点的角度
theta = pi * rand(num, 1);

% 从(radius - 0.5)到(radius + 0.5)均匀地生成点的半径
r = radius + 0.5 * (rand(num, 1) - 0.5);

% 计算点的x坐标和y坐标
x = r .* cos(theta);
y = r .* sin(theta);

% 给坐标加上一些随机噪声
x = x + noise * randn(num, 1);
y = y + noise * randn(num, 1);

% 根据偏移量平移点的位置
x = x + offset;
y = y - offset;

% 将坐标拼接成一个矩阵
data = [x y];
end

四、AGNES算法的总结和建议

AGNES算法是一种自底向上的层次聚类方法,它可以将数据集中的对象按照相似度逐步合并成一个大的簇。在使用AGNES算法时,我们需要注意以下几点:

  • 选择合适的距离或者相似度度量,根据数据的特点和需求,构建一个反映数据结构的邻接矩阵。
  • 选择合适的连接方式,根据不同的连接方式,计算不同簇之间的距离或者相似度,并且影响合并过程中产生的树形结构。
  • 选择合适的水平线位置,根据实际问题或者数据特点,从树形结构中切断一条水平线,得到最终的簇划分。

以上就是AGNES算法的全部内容啦~有帮助点个小赞收藏起来,会持续更新其他算法的实现

这里是希望和大家一起进步的小高,愿意和读者们热情探讨😊

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Agnes算法是一种层次聚类算法,它通过计算数据点之间的距离来将数据点逐步聚合成簇。在每一步中,算法会找到距离最近的两个数据点,然后将它们合并到一个新的簇中。这个新的簇将会作为下一步聚合的单个数据点。 在Agnes算法中,我们需要定义一个距离度量方法来衡量两个数据点之间的距离。常用的方法有欧氏距离、曼哈顿距离等。然后,我们需要定义一个合并标准来判断两个簇是否可以合并。常见的合并标准有最小距离、最大距离、平均距离等。 在Python中,可以使用SciPy库中的`scipy.cluster.hierarchy`模块来实现Agnes算法。首先,我们需要使用`scipy.spatial.distance`模块来计算数据点之间的距离。然后,我们可以使用`scipy.cluster.hierarchy.linkage`函数来进层次聚类。这个函数会根据之前定义的距离度量方法和合并标准来计算簇的合并顺序。最后,我们可以使用`scipy.cluster.hierarchy.dendrogram`函数来可视化聚类结果。 下面是一个简单的示例代码: ```python import numpy as np from scipy.spatial.distance import pdist from scipy.cluster.hierarchy import linkage, dendrogram # 生成数据 data = np.random.rand(20, 2) # 计算距离 distances = pdist(data) # 进层次聚类 clusters = linkage(distances) # 可视化聚类结果 dendrogram(clusters) # 展示结果 plt.show() ``` 通过运上述代码,我们可以得到一个层次聚类的树状图,根据树状图可以判断数据点之间的聚类关系。 总之,Agnes算法是一种基于层次聚类的算法,可以将数据点逐步聚合成簇。Python中可以使用SciPy库来实现Agnes算法,并通过可视化来分析聚类结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gavana.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值