基于双阈值预处理的Canopy聚类算法及MATLAB实现
算法核心机制
Canopy聚类是一种轻量级的粗粒度划分策略,主要用于高维数据的快速预处理。该算法不依赖复杂的迭代优化,而是通过设定两个距离阈值($T_1$ 与 $T_2$,且 $T_1 > T_2$)对特征空间中的样本进行分层过滤。其核心流程如下:
- 初始化包含所有样本的候选集合,并设定宽松阈值 $T_1$ 与严格阈值 $T_2$。
- 从候选集中随机抽取一个数据点作为新Canopy的初始中心,并将其移出集合。
- 遍历剩余样本,计算各点与当前中心的距离。若距离小于 $T_2$,则判定为强归属,直接将该点从候选集中剔除(避免其成为其他Canopy的中心);若距离介于 $T_2$ 与 $T_1$ 之间,则标记为弱归属(该点保留在候选集中,允许重叠划分);若距离大于 $T_1$,则不作处理。
- 重复上述步骤,直至候选集为空。最终生成一组可能存在交集的Canopy子集。

该算法通常不作为独立的聚类方案,而是作为K-Means等精确聚类算法的前置步骤。通过快速剔除噪声点与孤立点,并预估初始簇中心数量,可显著降低后续精细聚类的计算复杂度。
阈值配置策略
算法的划分质量高度依赖于 $T_1$ 和 $T_2$ 的设定:
- $T_1$ 过大:导致Canopy覆盖范围过广,簇间重叠率升高,中心点分布密集,削弱预聚类效果。
- $T_2$ 过大:强归属区域扩张,大量样本被提前剔除,最终生成的簇数量偏少,可能掩盖真实数据结构。
- $T_2$ 过小:核心区域收缩,候选集剔除效率降低,生成的簇数量激增,同时增加距离计算开销。
工程实践中,常通过对数据子集进行抽样,计算样本间距离的均值与标准差,动态推导合理的阈值区间。
MATLAB实现代码
以下实现基于Iris数据集,采用动态阈值估算与向量化距离计算,通过多次蒙特卡洛实验统计稳定的簇数量分布。
clear; clc;
% 载入特征矩阵(剔除末尾类别标签)
dataset = dlmread('iris.data');
X = dataset(:, 1:end-1);
[N, D] = size(X);
runs = 100;
K_history = zeros(runs, 1);
MAX_K = 20;
for r = 1:runs
% 抽取10%子集估算距离分布特征
idx = randperm(N, ceil(N*0.1));
subset = X(idx, :);
pairDist = pdist(subset);
% 动态生成双阈值
T_weak = mean(pairDist) + 4 * std(pairDist); % 宽松边界 T1
T_strong = T_weak * 0.5; % 严格边界 T2
pool = X;
canopies = [];
k = 0;
while ~isempty(pool) && k < MAX_K
k = k + 1;
centroid = pool(1, :);
canopies = [canopies; centroid];
pool(1, :) = []; % 移除已选中心
if isempty(pool), break; end
% 批量计算欧氏距离平方
delta = pool - centroid;
d2 = sum(delta.^2, 2);
% 强阈值内的点直接移出候选池,不参与后续中心竞争
removeIdx = d2 < T_strong^2;
pool(removeIdx, :) = [];
end
K_history(r) = k;
end
% 统计多次实验的聚类数目分布
tabulate(K_history)
运行结果与分析
Value Count Percent
1 0 0.00%
2 0 0.00%
3 98 98.00%
4 2 2.00%
5 0 0.00%
实验输出表明,在设定的阈值策略下,算法在绝大多数迭代中稳定输出 $K=3$ 的划分结果,与Iris数据集的真实类别数高度吻合。由于Canopy的生成过程依赖随机抽样与阈值截断,最终簇数量会随 $T_2$ 的缩放产生波动。在实际应用中,可将此结果直接作为K-Means的初始 $K$ 值与中心点先验,从而规避传统聚类算法对初始参数敏感的问题。