经典聚类算法讲解:K-means 和 DBSCAN
目录
一、K-means 算法
1. 核心思想
2. 算法步骤
3. 优缺点
4.代码实现
二、DBSCAN 算法
1. 核心思想
2. 算法步骤
3. 优缺点
4.代码实现
三、核心对比与总结
如何选择?
一、K-means 算法
1. 核心思想
K-means 的核心思想是“物以类聚”。它试图将数据集划分为 K 个(用户预先指定的)紧凑的球形簇,使得同一个簇内的数据点尽可能相似(距离小),不同簇的数据点尽可能不相似(距离大)。
简单比喻:“平均分配”。
假设你有一堆散落的水果(数据点),你的目标是把它们分成 K 个篮子(簇)。K-means 的做法是:
-
先随便找 K 个水果作为篮子的中心点。
-
把每个水果放到离它最近的那个中心点对应的篮子里。
-
重新计算每个篮子里所有水果的平均位置,把这个平均位置作为新的篮子中心。
-
重复步骤2和3,直到篮子的中心点不再变化(或变化很小)。
2. 算法步骤
-
初始化:随机选择 K 个数据点作为初始的聚类中心(Centroids)。
-
分配步骤:对于数据集中的每一个数据点,计算它与 K 个中心点的距离(通常是欧氏距离),并将其分配给距离最近的中心点所在的簇。
-
更新步骤:对于每一个簇,重新计算该簇中所有数据点的平均值,并将该平均值作为新的聚类中心。
-
迭代:重复步骤2和3,直到满足终止条件(通常是指聚类中心不再发生变化,或达到最大迭代次数)。
3. 优缺点
-
优点:
-
简单高效:原理和实现都非常简单,计算速度快,适用于大规模数据集。
-
可扩展性好:对于新数据点,可以很方便地将其分配到已有的簇中。
-
-
缺点:
-
必须预先指定 K 值:K 值的选择通常很困难,需要依赖经验或使用“肘部法则”等方法预估。
-
对初始中心敏感:不同的初始中心可能导致完全不同的聚类结果。
-
对簇形状的假设:假设簇是凸形的、球状的,对于非球形簇(如环形、月牙形)效果很差。
-
对噪声和离群点敏感:由于使用均值更新中心,少数极端离群点会严重影响中心点的位置。
-
4.代码实现
在Matlab中,K-means算法可以直接使用已有函数。例如:
[idx, C] = kmeans(indices, num_gully, 'Distance', 'cityblock', 'Replicates', 10)
二、DBSCAN 算法
1. 核心思想
DBSCAN 的核心思想是“近朱者赤”。它基于密度来划分簇,认为一个簇是由一组密度相连的点组成的,并且能够将低密度区域的点标记为噪声(离群点)。它不需要预先指定簇的数量(K)。
核心概念:
-
核心点:在指定半径(
eps
)范围内,拥有超过最少数量(MinPts
)邻居的点。 -
边界点:在核心点的
eps
邻域内,但自身不满足核心点条件的点。 -
噪声点:既不是核心点也不是边界点的点。
简单比喻:“人群聚集”。
想象一个广场上散布着很多人(数据点)。DBSCAN 的目标是找出密集的人群(簇)。
-
你定义一个规则:只要一个人周围
eps
米内至少有MinPts
个人,那他就是“核心人物”(核心点),并以他为核心形成一个团体。 -
然后,这个核心人物周围
eps
米内所有的人(即使他周围人不多)也都属于这个团体(边界点)。 -
你再从这些新加入的成员里,如果发现也有人周围有很多人(也是核心人物),就把他们的“势力范围”也合并进来。
-
一直这样扩展,直到这个团体不能再扩大为止。
-
那些周围始终没人或者人很少的孤零零的人,就被认为是“噪声”(噪声点)。
2. 算法步骤
-
参数设置:设置邻域半径
eps
和最小点数MinPts
。 -
寻找核心点:遍历所有点,如果某个点的
eps
邻域内包含至少MinPts
个点,则将其标记为核心点,并创建一个新的簇。 -
密度扩展:从核心点出发,将其
eps
邻域内的所有点都归入同一个簇。然后,再以这些新加入的点(如果是核心点的话)为种子,继续这个过程,直到该簇不能再扩展为止。 -
迭代:重复步骤2和3,直到所有点都被访问过。
-
处理噪声:所有未被分配到任何簇的点都被标记为噪声。
3. 优缺点
-
优点:
-
不需要预先指定簇数量。
-
能发现任意形状的簇,对非球形簇效果很好。
-
对噪声和离群点鲁棒,能有效识别和处理它们。
-
-
缺点:
-
对参数敏感:
eps
和MinPts
的选择对结果影响巨大,参数调优较困难。 -
密度变化大的簇效果差:如果数据集中不同簇的密度差异很大,很难用一个全局的
eps
和MinPts
参数来同时处理好所有簇。 -
高维数据表现不佳:在高维空间中,所有点对的距离都变得相似,使得“距离”概念失效,难以定义密度。
-
4.代码实现
给出Matlab实现如下:
function [idx, numClusters] = DBSCAN(data, epsilon, minPts)n = size(data, 1); % 样本数量idx = zeros(n, 1);clusterIdx = 0;% 计算样本之间的距离矩阵D = pdist2(data, data);% 遍历每个样本for i = 1:nif idx(i) == 0% 判断是否为核心样本neighborPts = find(D(i,:) <= epsilon);if length(neighborPts) < minPtsidx(i) = -1; % 噪声点elseclusterIdx = clusterIdx + 1;expandCluster(i, neighborPts, clusterIdx);endendendnumClusters = clusterIdx;function expandCluster(i, neighborPts, clusterIdx)idx(i) = clusterIdx;k = 1;while k <= length(neighborPts)j = neighborPts(k);if idx(j) == -1idx(j) = clusterIdx;elseif idx(j) == 0idx(j) = clusterIdx;nextNeighborPts = find(D(j,:) <= epsilon);if length(nextNeighborPts) >= minPtsneighborPts = [neighborPts, nextNeighborPts];endendk = k + 1;endend
end
三、核心对比与总结
特性 | K-means | DBSCAN |
---|---|---|
核心思想 | 距离划分,最小化簇内方差 | 密度相连,最大化密度扩展 |
簇形状 | 只能发现球形簇 | 能发现任意形状的簇 |
簇数量 | 必须预先指定 K | 无需指定,自动确定 |
噪声处理 | 非常敏感,会严重影响中心点 | 非常鲁棒,能直接识别噪声点 |
参数 | K(簇数) | eps (半径),MinPts (最小点数) |
结果稳定性 | 对初始中心点选择敏感,多次运行结果可能不同 | 对参数敏感,但参数固定后,多次运行结果稳定 |
计算效率 | 高效,适用于大规模数据 | 低维数据效率尚可,高维数据效率较低 |
适用场景 | 数据集庞大、簇呈球形分布、簇大小均匀 | 簇形状复杂、含有噪声、簇数量未知 |
如何选择?
-
当你知道数据大概要分成几类,且簇的形状大致是球形时,优先选择 K-means。它简单、快速,是很多应用的首选。
-
当你不知道数据有多少类,或者数据中有噪声和离群点,或者簇的形状奇形怪状(如环绕状)时,应该选择 DBSCAN。