聚类算法详解

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

一、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适合非凸簇和异常检测)。

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

相关推荐
刀法如飞2 小时前
Go 字符串查找的 20 种实现方式,用不同思路解决问题
算法·面试·程序员
Dlrb12114 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
WL_Aurora4 小时前
Python 算法基础篇之集合
python·算法
平行侠4 小时前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完5 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表
li星野5 小时前
位运算 & 数学 & 高频进阶九题通关(Python + C++)
c++·python·学习·算法
jerryinwuhan5 小时前
hello算法,简单讲(1)
算法·排序算法
y = xⁿ5 小时前
20天速通LeetCodeday15:BFS广度优先搜索
算法·宽度优先
400分5 小时前
吃透RAG核心-----语义检索与关键字检索底层原理
算法·架构