ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

鸢尾花聚类实战:k均值、合并聚类与DBSCAN结果差异与调参指南

鸢尾花聚类实战:k均值、合并聚类与DBSCAN结果差异与调参指南 简介这份资源面向机器学习初学者与需要巩固无监督学习基础的开发者围绕鸢尾花数据集给出三种经典聚类算法的完整实现帮助读者理解不同聚类思路的差异与适用场景。压缩包共6个文件以5个Python脚本和1份doc说明文档为主整体约433KB脚本分别对应k均值、合并聚类与DBSCAN的实现及在鸢尾花数据上的调用示例文档则对算法原理与流程做补充讲解。内容涵盖k均值质心迭代、凝聚式层次合并、DBSCAN密度可达与参数设置等核心知识点便于读者对照代码观察聚类效果并比较各算法优缺点。目前已有2321人学习下载适合希望快速上手聚类实践、为后续项目选型积累经验的学习者参考。1. 三套聚类代码跑同一份鸢尾花为什么结果差这么多鸢尾花数据集只有 150 行、4 个特征很多人第一次做聚类就拿它练手跑完 k 均值发现准确率还行换成 DBSCAN 直接崩了合并聚类又不知道参数怎么设。问题不在数据在于三种算法对“簇”的定义根本不同k 均值假设簇是球形且大小相近合并聚类按距离阈值逐步合并DBSCAN 靠密度连通性找任意形状的簇。同一份鸢尾花k 均值在标准化后能拿到 0.9 左右的调整兰德指数DBSCAN 在默认参数下可能把大部分点判成噪声合并聚类则对链接方式极度敏感。这篇笔记把三套代码的落地路径拆开从数据标准化、参数搜索到结果评估每一步都给可复现的命令和参数说明适合已经会用 sklearn 但被聚类结果不稳定困扰的从业者。2. 数据准备与标准化鸢尾花聚类的第一道分水岭2.1 加载鸢尾花并确认特征量纲鸢尾花数据集在 sklearn 里直接可用但很多人忽略了一个事实四个特征的单位都是厘米量纲一致所以不做标准化也能跑。但 DBSCAN 和合并聚类对距离敏感标准化后结果更稳。我一般先加载数据打印描述性统计确认没有缺失值。from sklearn.datasets import load_iris import pandas as pd iris load_iris() X iris.data y iris.target df pd.DataFrame(X, columnsiris.feature_names) print(df.describe()) print(标签分布:, pd.Series(y).value_counts().to_dict())这段代码加载数据后输出统计量。load_iris()返回的data是 150×4 的数组target是 0/1/2 三分类标签。describe()看均值和标准差如果某个特征标准差远大于其他标准化就有必要。鸢尾花四个特征的标准差都在 0.2 到 0.8 之间量纲差异不大但花瓣宽度和萼片长度的均值差了近 10 倍标准化后距离计算更均衡。2.2 标准化与不标准化的对比实验标准化用StandardScaler把每个特征变成均值 0、方差 1。这一步对 k 均值影响不大但对 DBSCAN 的eps参数影响很大——不标准化时eps要设到 0.5 以上标准化后 0.3 到 0.5 就够。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X) print(标准化前均值:, X.mean(axis0).round(2)) print(标准化后均值:, X_scaled.mean(axis0).round(2)) print(标准化后标准差:, X_scaled.std(axis0).round(2))fit_transform先算均值和方差再变换。标准化后每列均值接近 0标准差接近 1。注意聚类是无监督任务标准化要用全部数据拟合不能像分类那样分训练测试集。如果后续要评估用调整兰德指数ARI对比真实标签但标准化必须用全量数据。提示如果鸢尾花数据是从 xlsx 文件读的列名可能带空格或中文先df.columns df.columns.str.strip()再取.values否则 sklearn 会报特征名不匹配。3. k 均值聚类簇数怎么定、初始化怎么选3.1 k 均值的核心参数与肘部法k 均值只有两个关键参数n_clusters和n_init。n_clusters决定簇数n_init是不同初始化跑几次取最优。sklearn 从 1.4 开始n_init默认是auto等价于 1 次但实际用的时候我建议显式设成 10避免陷入局部最优。from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertias [] K_range range(1, 11) for k in K_range: km KMeans(n_clustersk, n_init10, random_state42) km.fit(X_scaled) inertias.append(km.inertia_) plt.plot(K_range, inertias, markero) plt.xlabel(簇数 k) plt.ylabel(簇内平方和) plt.title(肘部法确定 k) plt.show()inertia_是每个点到其簇中心的距离平方和。k 增大时 inertia 单调下降拐点就是候选 k。鸢尾花真实有 3 类肘部法通常在 k3 附近出现明显拐弯。random_state42保证每次初始化一致方便复现。n_init10表示跑 10 次不同初始中心取 inertia 最小的那次。3.2 用轮廓系数验证 k 值肘部法靠肉眼轮廓系数更客观。轮廓系数范围 -1 到 1越接近 1 说明簇内越紧、簇间越远。from sklearn.metrics import silhouette_score for k in range(2, 7): km KMeans(n_clustersk, n_init10, random_state42) labels km.fit_predict(X_scaled) score silhouette_score(X_scaled, labels) print(fk{k}, 轮廓系数{score:.4f})fit_predict返回每个样本的簇标签。silhouette_score计算全量样本的平均轮廓系数。鸢尾花在 k2 时轮廓系数往往最高因为其中两类在特征空间有重叠k 均值强行分 3 类会拉低分数。这时候要结合业务判断如果已知有三类就选 k3轮廓系数只作参考。3.3 k 均值结果评估与混淆矩阵聚类没有标签但鸢尾花有真实标签可以用 ARI 和混淆矩阵看聚类效果。from sklearn.metrics import adjusted_rand_score, confusion_matrix km KMeans(n_clusters3, n_init10, random_state42) labels km.fit_predict(X_scaled) ari adjusted_rand_score(y, labels) print(调整兰德指数:, round(ari, 4)) print(混淆矩阵:) print(confusion_matrix(y, labels))ARI 取值 -1 到 10 表示随机1 表示完全一致。鸢尾花上 k 均值标准化后 ARI 通常在 0.6 到 0.75 之间。混淆矩阵看哪些类被混了——通常 versicolor 和 virginica 互相错分因为这两个类在花瓣长度和宽度上重叠。confusion_matrix的行是真实标签列是聚类标签聚类标签顺序和真实标签顺序不一定对应看的时候要手动对齐。4. 合并聚类链接方式决定成败4.1 凝聚层次聚类的三种链接准则合并聚类凝聚层次聚类从每个点一个簇开始每次合并距离最近的两个簇。关键参数是linkageward最小化合并后的方差complete用两组间最远点距离average用平均距离。鸢尾花上ward通常最好因为它在欧氏距离下倾向于产生大小相近的球形簇。from sklearn.cluster import AgglomerativeClustering for linkage in [ward, complete, average]: ac AgglomerativeClustering(n_clusters3, linkagelinkage) labels ac.fit_predict(X_scaled) ari adjusted_rand_score(y, labels) print(flinkage{linkage}, ARI{ari:.4f})AgglomerativeClustering不需要指定n_init因为它是确定性算法。ward只能配合欧氏距离complete和average可以配合其他距离但 sklearn 只支持欧氏。跑完对比 ARIward在鸢尾花上一般能到 0.7 以上average可能只有 0.5 左右。4.2 树状图与距离阈值合并聚类可以画树状图看合并过程用 scipy 的dendrogram。from scipy.cluster.hierarchy import dendrogram, linkage import matplotlib.pyplot as plt Z linkage(X_scaled, methodward) plt.figure(figsize(10, 6)) dendrogram(Z, truncate_modelastp, p20) plt.title(ward 链接树状图) plt.xlabel(样本索引或簇大小) plt.ylabel(合并距离) plt.show()linkage返回一个 4 列的矩阵每行记录一次合并。dendrogram画树状图truncate_modelastp只显示最后 20 个合并避免 150 个叶子挤在一起。看树状图找最大的垂直距离在那个位置切一刀就是簇数。鸢尾花在距离 10 左右切能得到 3 簇。4.3 合并聚类的计算复杂度与适用边界合并聚类的时间复杂度是 O(n³)朴素实现或 O(n² log n)优化后空间 O(n²)。150 行数据无所谓但上万行就吃不消。我一般只在数据量小于 5000 时用合并聚类再大就换 k 均值或 DBSCAN。另外合并聚类一旦合并就不能撤销早期错误合并无法修正这是它和 k 均值最大的区别。注意AgglomerativeClustering的distance_threshold和n_clusters只能设一个。如果设distance_thresholdn_clusters必须为None否则报错。5. DBSCAN密度聚类在鸢尾花上的翻车与调参5.1 DBSCAN 的两个核心参数eps 和 min_samplesDBSCAN 靠eps邻域半径和min_samples邻域内最少点数定义核心点。核心点的 eps 邻域内至少有 min_samples 个点密度可达的点连成簇不满足的判为噪声。鸢尾花上默认eps0.5、min_samples5经常把大量点判成噪声因为标准化后点间距离集中在 0.5 到 1.5 之间。from sklearn.cluster import DBSCAN from sklearn.neighbors import NearestNeighbors import numpy as np neighbors NearestNeighbors(n_neighbors5) neighbors.fit(X_scaled) distances, indices neighbors.kneighbors(X_scaled) distances np.sort(distances[:, 4], axis0) plt.plot(distances) plt.xlabel(样本排序) plt.ylabel(第 5 近邻距离) plt.title(k-距离图确定 eps) plt.show()NearestNeighbors(n_neighbors5)找每个点的 5 个最近邻kneighbors返回距离和索引。取第 5 列索引 4排序后画图拐点就是eps候选值。鸢尾花标准化后拐点通常在 0.6 到 0.8 之间。min_samples一般设成特征数加 1鸢尾花 4 个特征就设 5。5.2 用网格搜索找 DBSCAN 最优参数手动调参太慢写个循环遍历 eps 和 min_samples。best_ari -1 best_params {} for eps in np.arange(0.3, 1.2, 0.1): for min_samples in [3, 5, 7, 10]: db DBSCAN(epseps, min_samplesmin_samples) labels db.fit_predict(X_scaled) n_clusters len(set(labels)) - (1 if -1 in labels else 0) if n_clusters 2: continue ari adjusted_rand_score(y, labels) if ari best_ari: best_ari ari best_params {eps: round(eps, 2), min_samples: min_samples} print(最优参数:, best_params) print(最优 ARI:, round(best_ari, 4))fit_predict返回标签-1 表示噪声。len(set(labels))算簇数时要排除 -1。如果簇数小于 2 就跳过因为 ARI 对单簇无意义。鸢尾花上最优 eps 通常在 0.6 到 0.8min_samples 在 5 到 7ARI 能到 0.5 到 0.6比 k 均值低因为 DBSCAN 会把边界点判成噪声。5.3 DBSCAN 噪声点处理与结果解读DBSCAN 的噪声点不是错误是密度不够的点。鸢尾花里 versicolor 和 virginica 交界处的点经常被标为 -1。db DBSCAN(eps0.7, min_samples5) labels db.fit_predict(X_scaled) n_noise list(labels).count(-1) print(f噪声点数: {n_noise}, 占比: {n_noise/len(labels):.2%}) print(各簇样本数:, pd.Series(labels).value_counts().to_dict())list(labels).count(-1)数噪声。如果噪声占比超过 30%说明 eps 太小或 min_samples 太大。鸢尾花上合理噪声占比在 5% 到 15%。噪声点可以单独拿出来看往往就是两类重叠区域的样本。实际业务里噪声点可能代表异常样本不要直接丢掉先分析来源。6. 避坑与排查三种聚类算法最容易翻车的五个地方6.1 标准化做了但没对齐特征顺序现象从 xlsx 读的鸢尾花数据列顺序和 sklearn 不一致聚类结果完全乱套。原因xlsx 里列可能是“萼片长、萼片宽、花瓣长、花瓣宽”但 sklearn 是“萼片长、萼片宽、花瓣长、花瓣宽”——顺序一样但有人手动改过列名或删过列。解决读入后打印df.columns和iris.feature_names对比用df df[iris.feature_names]强制对齐再.values转数组。6.2 k 均值 n_init 用默认值导致结果不稳定现象同样的数据和 k跑两次结果不一样ARI 差 0.1 以上。原因sklearn 1.4 之前n_init默认 10之后改成auto只跑 1 次初始化不好就陷局部最优。解决显式写n_init10或n_init20并固定random_state。如果数据量大用initk-means加速收敛。6.3 DBSCAN 的 eps 用默认 0.5 导致全判噪声现象DBSCAN 跑完所有点都是 -1或者只有一个簇加一堆噪声。原因标准化后点间距离分布变了默认 eps0.5 太小核心点条件不满足。解决画 k-距离图找拐点或者网格搜索 eps 从 0.3 到 1.2。min_samples 从 3 开始试不要一上来设 10。6.4 合并聚类 ward 链接配合非欧距离报错现象AgglomerativeClustering(linkageward, affinitymanhattan)直接抛异常。原因ward 链接的数学推导基于欧氏距离sklearn 限制只能配affinityeuclidean。解决要用曼哈顿距离就换linkageaverage或complete但效果可能下降。鸢尾花上老老实实用 ward euclidean。6.5 用 ARI 评估时聚类标签和真实标签顺序不对应现象混淆矩阵看起来全错但 ARI 很高。原因聚类标签是任意分配的簇 0 可能对应真实类 2簇 1 对应真实类 0。解决用confusion_matrix看对应关系或者用匈牙利算法对齐标签后再算准确率。ARI 本身对标签置换不变所以 ARI 高就说明聚类结构对不用管标签顺序。7. 三套代码怎么选一个快速决策表和调参习惯三种算法没有绝对优劣看数据形状和业务目标。我整理了一个决策表按数据量、簇形状、噪声容忍度来选。场景推荐算法关键参数鸢尾花上预期 ARI数据量小于 5000簇近似球形k 均值n_clusters3, n_init100.65~0.75数据量小于 5000不想预设簇数合并聚类 wardn_clusters3, linkageward0.70~0.78数据有噪声簇形状不规则DBSCANeps0.7, min_samples50.50~0.60数据量大于 10000MiniBatchKMeansn_clustersk, batch_size1024略低于 k 均值调参习惯上我一般先跑 k 均值定基准再用合并聚类看层次结构最后用 DBSCAN 找噪声。如果三种算法给出的簇结构一致说明数据本身分离度好如果差异大就回到特征工程看是不是某些特征在干扰距离计算。鸢尾花上花瓣长度和花瓣宽度是最有区分度的两个特征只用这两个特征跑 k 均值ARI 能到 0.85 以上比用全部四个特征还高——这也是我踩过的坑特征不是越多越好冗余特征会稀释距离信号。最后一个技巧把三种算法的标签拼成一个 DataFrame看哪些样本在所有算法里都被分到同一簇这些是“铁杆核心点”哪些样本在不同算法间跳来跳去这些是边界点值得单独分析。这个习惯帮我省了很多调参时间也让我对数据的理解从“跑通代码”变成“看懂结构”。希望帮到你。本文还有配套的精品资源点击获取
返回列表