ARTICLE DETAIL

资讯详情

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

ML-For-Beginners 聚类实战:用 Scikit-learn K-Means 对尼日利亚音乐数据建模(Silhouette 评分、Elbow 方法与方差问题)

ML-For-Beginners 聚类实战:用 Scikit-learn K-Means 对尼日利亚音乐数据建模(Silhouette 评分、Elbow 方法与方差问题) ML-For-Beginners 聚类实战用 Scikit-learn K-Means 对尼日利亚音乐数据建模Silhouette 评分、Elbow 方法与方差问题【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本篇技术指南完整复现 ML-For-Beginners 课程《K-Means clustering》的核心实验基于 5-Clustering/data/nigerian-songs.csv尼日利亚 Spotify 音乐数据使用 Scikit-learn 的 K-Means 对 3 种音乐流派进行无监督聚类并深入讲解 Silhouette 评分、Elbow 方法、惯性inertia与方差variance四大核心概念。读完本文你将掌握 K-Means 的完整建模流程、聚类质量的量化评估方法以及当数据不适合 K-Means 时如何通过特征缩放等策略定位并改进问题。课程背景与实验目标本节课程属于 ML-For-Beginners 的 5-Clustering 聚类单元承接上一课《Introduction to clustering》见 5-Clustering/1-Visualize/README.md。上一课已经完成了数据的导入、探索与初步清洗数据共 530 条记录、16 列包含name、artist、artist_top_genre、popularity、danceability、acousticness、energy、loudness等音乐特征且无空值。本课的目标是用 K-Means 算法对歌曲数据做无监督聚类不依赖标签学习 Silhouette 评分Silhouette scoring、Elbow 方法Elbow method、惯性Inertia、方差Variance四个核心术语通过先尝试、再评估、后诊断的完整流程理解为什么有些数据天然不适合 K-Means。实验基于本课配套的 5-Clustering/2-K-Means/notebook.ipynb其中已包含上一课完成的数据导入与初步过滤逻辑。K-Means 聚类原理从 Voronoi 图到三步迭代K-MeansK 均值聚类源自信号处理领域是一种基于质心centroid的划分式聚类方法。它的核心思想是将数据集划分为k个簇每个观测样本都被分配到离它最近的均值即簇中心点所在的簇。簇的几何结构可以用 Voronoi 图Voronoi diagram来可视化每个簇对应一个种子点seed种子点周围的区域即该簇的决策区域任何落在这个区域内的样本都属于该种子对应的簇。Scikit-learn 文档将 K-Means 的执行过程概括为三步迭代算法从数据集中采样选出k个初始中心点进入循环迭代将每个样本分配到最近的质心取所有已分配样本的均值生成新的质心计算新旧质心之间的差异重复迭代直到质心稳定不再显著移动。K-Means 最大的缺点是必须预先指定k质心数量。幸运的是Elbow 方法肘部法可以帮助估计一个合理的k初始值我们稍后会实际尝试。动手实验一数据准备与离群值观察课程配套的 notebook5-Clustering/2-K-Means/notebook.ipynb在前课基础上首先将数据聚焦到 3 个主要流派并过滤掉popularity为 0无排名的歌曲df pd.read_csv(../../data/nigerian-songs.csv) # 只保留 3 个主要流派 df df[(df[artist_top_genre] afro dancehall) | (df[artist_top_genre] afropop) | (df[artist_top_genre] nigerian pop)] # 过滤掉 popularity 为 0 的歌曲 df df[(df[popularity] 0)]接着对每一列绘制箱线图boxplot用plt.subplot将 12 个特征排成 4 行 3 列plt.figure(figsize(20,20), dpi200) plt.subplot(4,3,1) sns.boxplot(x popularity, data df) plt.subplot(4,3,2) sns.boxplot(x acousticness, data df) plt.subplot(4,3,3) sns.boxplot(x energy, data df) plt.subplot(4,3,4) sns.boxplot(x instrumentalness, data df) plt.subplot(4,3,5) sns.boxplot(x liveness, data df) plt.subplot(4,3,6) sns.boxplot(x loudness, data df) plt.subplot(4,3,7) sns.boxplot(x speechiness, data df) plt.subplot(4,3,8) sns.boxplot(x tempo, data df) plt.subplot(4,3,9) sns.boxplot(x time_signature, data df) plt.subplot(4,3,10) sns.boxplot(x danceability, data df) plt.subplot(4,3,11) sns.boxplot(x length, data df) plt.subplot(4,3,12) sns.boxplot(x release_date, data df)从箱线图可以直观看到数据是有点嘈杂的多个特征存在明显的离群值outliers。理论上可以逐列剔除离群值但这会让数据变得非常稀少得不偿失因此本课选择保留这些数据改为挑选数值范围相近的列用于聚类。动手实验二特征选择与标签编码接下来挑选用于聚类的特征。课程选择了取值范围相近的 6 个特征artist_top_genre、popularity、danceability、acousticness、loudness、energy。由于 K-Means 只能处理数值数据需要使用LabelEncoder将流派名称如afro dancehall、afropop、nigerian pop编码为整数from sklearn.preprocessing import LabelEncoder le LabelEncoder() X df.loc[:, (artist_top_genre,popularity,danceability,acousticness,loudness,energy)] y df[artist_top_genre] X[artist_top_genre] le.fit_transform(X[artist_top_genre]) y le.transform(y)这里X是聚类使用的特征矩阵y保留流派标签仅用于后续评估聚类与真实类别的吻合度。注意聚类本身是无监督的y不参与模型训练只在评估阶段用于对比。动手实验三训练 K-Means 与 Silhouette 评分已知数据集中包含 3 个主要流派先假设k 3进行尝试from sklearn.cluster import KMeans nclusters 3 seed 0 km KMeans(n_clustersnclusters, random_stateseed) km.fit(X) # Predict the cluster for each data point y_cluster_kmeans km.predict(X) y_cluster_kmeans运行后会输出一个数组其中每个元素是该行数据被预测到的簇编号0、1 或 2。这些编号本身没有业务含义需要用指标来量化聚类质量。下一步用 Scikit-learn 的metrics.silhouette_score计算 Silhouette 评分from sklearn import metrics score metrics.silhouette_score(X, y_cluster_kmeans) scoreSilhouette 评分解读Silhouette 评分的取值范围是-1 到 1含义如下取值含义接近 1簇内稠密、簇间分离良好聚类质量高接近 0簇与簇重叠样本非常靠近相邻簇的决策边界接近 -1样本很可能被分配到了错误的簇本实验中评分约为0.53恰好落在中间。这说明数据并非特别适合这种聚类方式但课程选择继续推进用 Elbow 方法来验证k3是否合理。动手实验四构建模型与 Elbow 方法为了用 Elbow 方法确认最优簇数需要计算不同k值下的 WCSS簇内平方和。课程代码对k从 1 到 10 循环训练 K-Means并把每次的inertia_存入wcss列表from sklearn.cluster import KMeans wcss [] for i in range(1, 11): kmeans KMeans(n_clusters i, init k-means, random_state 42) kmeans.fit(X) wcss.append(kmeans.inertia_)这段代码里有几个值得展开解释的关键参数range(1, 11)对聚类过程进行 10 次迭代每次尝试不同的簇数量。random_state决定质心初始化的随机数生成。设置固定值如42可以保证结果可复现这在调参与对比实验时非常重要。WCSSwithin-cluster sums of squares即簇内平方和度量一个簇内所有点到该簇质心的平方平均距离。WCSS 越小说明簇内越紧凑。inertia_惯性K-Means 算法试图选择质心以最小化惯性Scikit-learn 官方将其描述为衡量簇内部一致性internally coherent的指标。每次迭代后该值被追加到wcss变量中。initk-meansScikit-learn 提供的质心初始化优化策略。它让初始质心彼此大体上相距较远相比完全随机初始化通常能产生更好的结果。这也是 Scikit-learn 中KMeans的默认初始化方式。绘制肘部曲线用wcss变量绘制折线图观察肘部拐点bend出现在哪里plt.figure(figsize(10,5)) sns.lineplot(xrange(1, 11), ywcss, markero, colorred) plt.title(Elbow) plt.xlabel(Number of clusters) plt.ylabel(WCSS) plt.show()肘部曲线横轴是簇数量、纵轴是 WCSS。随着k增大WCSS 必然单调下降簇越多簇内越紧凑但下降速度会在某个点之后明显放缓这个拐点对应的k就是相对最优的簇数。从结果来看拐点确实出现在 3 附近——最初的猜测3 个流派对应 3 个簇得到了印证。动手实验五展示聚类结果与准确率评估确认k3后重新拟合模型并用散点图可视化聚类结果from sklearn.cluster import KMeans kmeans KMeans(n_clusters 3) kmeans.fit(X) labels kmeans.predict(X) plt.scatter(df[popularity],df[danceability],c labels) plt.xlabel(popularity) plt.ylabel(danceability) plt.show()将聚类标签与真实流派标签做对比评估分类准确率labels kmeans.labels_ correct_labels sum(y labels) print(Result: %d out of %d samples were correctly labeled. % (correct_labels, y.size)) print(Accuracy score: {0:0.2f}. format(correct_labels/float(y.size)))这个模型的准确率并不理想。散点图揭示了原因数据高度不平衡、特征之间相关性很弱、列与列之间的方差过大导致无法形成清晰分离的簇。实际形成的簇很可能被上述定义的 3 个流派类别强烈影响甚至扭曲。正如课程所说这是一次学习过程——模型暴露了数据与算法的失配这正是无监督学习中非常典型的一课。方差VarianceK-Means 失配的根源方差被定义为与均值的平方差的平均值。在这个聚类问题的语境下它指的是数据集中各特征的数值偏离均值过远、分布过于发散。Scikit-learn 官方文档用一组示意图展示了类似的问题当簇的分界不清晰时模型往往存在方差问题——例如簇数量判断错误incorrect number of blobs、簇呈各向异性分布、簇内方差不等、簇大小不均等情形都会让 K-Means 的聚类质量大打折扣。本文使用的popularity与danceability数据正属于这种不够理想的分布。改进思路特征缩放课程提供了一个关键改进方向对数据进行缩放scaling将其归一化到相近的量纲范围后再聚类。在配套的解答笔记本 5-Clustering/2-K-Means/solution/notebook.ipynb 中可以看到使用StandardScaler的标准缩放代码默认处于注释状态供读者自行启用实验from sklearn.preprocessing import LabelEncoder, StandardScaler le LabelEncoder() # scaler StandardScaler() X df.loc[:, (artist_top_genre,popularity,danceability,acousticness,loudness,energy)] y df[artist_top_genre] X[artist_top_genre] le.fit_transform(X[artist_top_genre]) # X scaler.fit_transform(X) y le.transform(y)取消scaler StandardScaler()与X scaler.fit_transform(X)两行的注释即可对比缩放前后的效果。实验会发现缩放后 Silhouette 评分会下降但肘部曲线的拐点会被磨平。原因在于——不缩放数据时方差较小的列反而承担了更大的权重因为 K-Means 基于欧氏距离量纲大的特征会主导距离计算缩放后各列权重均衡但原本恰好可分的表象也随之消失。这说明本数据集的内在结构对 K-Means 并不友好需要从数据清洗、特征选择或更换算法等更根本的层面入手。挑战与课后作业课程在 5-Clustering/2-K-Means/README.md 末尾给出了两个层次的实践任务 挑战花时间修改 notebook 中的参数。可以通过更彻底地清洗数据例如剔除离群值来提升准确率吗可以使用权重weights给特定数据样本更大的影响吗还能做些什么来生成更好的簇作业参见 5-Clustering/2-K-Means/assignment.md——尝试不同的聚类方法。用本课程或其他来源的数据需注明出处创建一个 notebook展示一种不使用 K-Means的聚类方法并总结学到的经验。评分标准要求提交一个文档完善的聚类模型 notebook 为优秀文档不完整或不完善为合格提交不完整作品则需改进。关于聚类方法的选型可参考上一课 5-Clustering/1-Visualize/README.md 中的对照表K-Means 适合通用、归纳式场景DBSCAN、OPTICS 适合非平面几何与不均匀簇谱聚类Spectral clustering适合少量均匀簇高斯混合Gaussian mixtures适合平面几何数据等。当数据像本课这样不平衡、低相关、高方差时换一种与数据几何特性匹配的算法往往是比硬调参数更有效的出路。小结本课通过一次完整的 K-Means 实战串联起了无监督聚类的完整方法论数据准备箱线图找离群值→ 特征选择与编码 → 假设簇数并训练 → Silhouette 评分量化质量 → Elbow 方法验证簇数 → 可视化与准确率评估 → 方差诊断与缩放改进。最终得到的核心结论是K-Means 虽是最常用的聚类算法但它对数据分布有隐含假设近似球形簇、各特征尺度相近、簇大小均匀当数据不满足这些假设时评分指标会诚实地告诉你——这时需要回到数据层面清洗、缩放、换特征或算法层面换用密度聚类、层次聚类等继续迭代。这正是无监督学习中评估驱动改进的工程思维。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表