聚类算法详解

聚类算法作为无监督学习的核心分支,就像一位"智能分类师",能在没有标签的数据集里,自动把相似的对象归为一类,把不同的对象分开。它广泛应用于客户分群、图像分割、异常检测等场景,接下来我们用通俗易懂的方式拆解常见聚类算法的原理、例子和代码实现。

一、K-Means聚类:最经典的"中心靠拢"算法

原理

K-Means是最常用的聚类算法之一,核心思想很简单:先指定要划分的类别数K,随机选取K个点作为初始聚类中心,然后反复做两件事:一是把每个样本分配到距离最近的中心所在的类别;二是根据每个类的样本重新计算新的聚类中心。直到聚类中心不再变化,或者变化很小,就完成了聚类。

可以类比成:老师要把学生分成K组,先随便选K个学生当组长,然后让其他学生选离自己"最合得来"的组长组队;组队后,每组重新选一个"最能代表大家"的新组长,再重复这个过程,直到每组的组长不再更换,分组就稳定了。

例子

比如电商平台要对用户分群,选取"月消费额"和"月购买次数"两个特征,假设指定K=3,K-Means就能自动把用户分成"高消费高频次""低消费低频次""中等消费中等频次"三类,方便平台针对不同群体做精准营销。

代码实现(Python)

我们用sklearn库实现K-Means,以经典的鸢尾花数据集为例(虽然鸢尾花有标签,但可以当作无监督数据来聚类):

python 复制代码
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# 加载数据,取前两个特征方便可视化
iris = load_iris()
X = iris.data[:, :2]

# 构建K-Means模型,指定聚类数为3
kmeans = KMeans(n_clusters=3, random_state=42)
y_pred = kmeans.fit_predict(X)

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis')
plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], 
            s=200, c='red', marker='X', label='聚类中心')
plt.xlabel('花萼长度')
plt.ylabel('花萼宽度')
plt.legend()
plt.title('K-Means聚类结果')
plt.show()

二、层次聚类:"树状图"式的逐步聚合/分裂

原理

层次聚类就像搭建一棵"分类树",分为两种方式:

  • 凝聚式(自下而上):一开始每个样本都是一个单独的类,然后不断把最相似的两个类合并,直到所有样本聚成一个类,或者达到指定的类别数。
  • 分裂式(自上而下):一开始所有样本是一个大类,然后不断把最不相似的类拆分,直到每个样本都是单独的类,或者达到指定类别数。

可以类比成:一堆散落在地上的积木,凝聚式就是先把相似的积木两两拼在一起,再把拼好的小模块继续合并,最后拼成一个大整体;分裂式则是先把所有积木看成一个大整体,然后慢慢拆成小模块,直到每个积木单独分开。

例子

在生物分类中,层次聚类可以用来构建物种的进化树:从单个物种开始,把亲缘关系近的物种逐步合并,最终形成一棵展示物种进化关系的树状图。

代码实现(Python)

用scipy和sklearn实现凝聚式层次聚类:

python 复制代码
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage

# 生成模拟数据
X, _ = make_blobs(n_samples=50, centers=3, random_state=42)

# 构建层次聚类模型
agg_clustering = AgglomerativeClustering(n_clusters=3)
y_pred = agg_clustering.fit_predict(X)

# 绘制树状图(基于linkage矩阵)
linked = linkage(X, 'ward')  # ward方法使合并后的类内方差最小
plt.figure(figsize=(10, 5))
dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
plt.title('层次聚类树状图')
plt.show()

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.title('凝聚式层次聚类结果')
plt.show()

三、DBSCAN:基于"密度"的异常检测能手

原理

DBSCAN(密度基于空间聚类的应用与噪声)不依赖预先指定类别数,它的核心是"密度":把样本分为三类------核心点(周围一定范围内有足够多的样本)、边界点(靠近核心点但自身不是核心点)、噪声点(既不是核心点也不是边界点)。聚类过程就是找到所有相互可达的核心点和边界点,形成一个类,噪声点则被单独区分出来。

可以类比成:在人群中,核心点就是周围有很多朋友的人,边界点是靠近这些"社交达人"但自己朋友不多的人,噪声点是孤零零站在角落的人。DBSCAN会把相互认识的"社交达人"和他们身边的人归为一群,角落的人就是异常。

例子

在信用卡欺诈检测中,正常交易的样本会形成密集的簇,而欺诈交易因为数量少、特征异常,会被DBSCAN识别为噪声点,从而快速定位异常交易。

代码实现(Python)

用sklearn实现DBSCAN:

python 复制代码
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt

# 生成模拟的"月亮形"数据(K-Means难以处理这种非凸数据)
X, _ = make_moons(n_samples=200, noise=0.05, random_state=42)

# 构建DBSCAN模型,eps是邻域半径,min_samples是邻域内最少样本数
dbscan = DBSCAN(eps=0.3, min_samples=5)
y_pred = dbscan.fit_predict(X)

# 可视化聚类结果(-1表示噪声点)
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.title('DBSCAN聚类结果(-1为噪声点)')
plt.show()

四、高斯混合模型(GMM):"概率化"的聚类算法

原理

GMM假设每个类别的样本都服从高斯分布(正态分布),整个数据集是多个高斯分布的混合。它的核心是通过EM算法(期望最大化),估计每个高斯分布的均值、方差,以及每个样本属于各个高斯分布的概率,最终根据概率最大的类别给样本归类。

可以类比成:有几台不同的机器在生产零件,每台机器生产的零件尺寸服从不同的正态分布,GMM就能通过零件尺寸数据,反推出有几台机器,以及每个零件更可能是哪台机器生产的。

例子

在图像分割中,GMM可以根据像素的颜色、亮度等特征,把图像分成不同的区域,比如把背景和前景分开,因为背景和前景的像素分布通常符合不同的高斯分布。

代码实现(Python)

用sklearn实现GMM:

python 复制代码
from sklearn.mixture import GaussianMixture
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=3, random_state=42)

# 构建GMM模型,指定组件数为3
gmm = GaussianMixture(n_components=3, random_state=42)
y_pred = gmm.fit_predict(X)

# 可视化聚类结果
plt.scatter(X[:, 0], X[:, 1], c=y_pred, cmap='viridis')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.title('高斯混合模型聚类结果')
plt.show()

以上只是常见聚类算法的基础介绍,实际应用中还有谱聚类、OPTICS等算法,不同算法适合不同的数据场景(比如K-Means适合凸形簇,DBSCAN适合非凸簇和异常检测)。

个人能力有限,文中介绍的算法原理和代码实现仅为基础入门内容,若需深入理解算法的数学推导和复杂场景下的调优技巧,还需参考专业书籍和学术资料进一步学习。

相关推荐
Frostnova丶6 小时前
【算法笔记】数学知识
笔记·算法
吴可可1237 小时前
AutoCAD 2016与2014二次开发关键差异
算法
雨白8 小时前
哈希:以时间换空间的算法实战
算法
San813_LDD10 小时前
[数据结构]LeetCode学习
数据结构·算法·图论
x1387028595710 小时前
c语言排雷游戏(基础版9*9)
c语言·算法·游戏
sheeta199811 小时前
LeetCode 每日一题笔记 日期:2026.06.06 题目:2196. 根据描述创建二叉树
笔记·算法·leetcode
小欣加油11 小时前
leetcode994 腐烂的橘子
数据结构·c++·算法·leetcode·bfs
QuZero12 小时前
Guava Cache Deep Dive
java·后端·算法·guava
随意起个昵称12 小时前
线性dp-LIS题目4(A Twisty Movement)
算法·动态规划