)
K-Means 聚类实战用 Scikit-learn 对尼日利亚音乐数据做无监督分群ML-For-Beginners 第 15 课【免费下载链接】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 课程第 15 课《K-Means 聚类》为核心结合本仓库 5-Clustering/2-K-Means 目录下的 notebook、解决方案与真实数据集完整讲解 K-Means 算法的三步迭代原理、轮廓系数Silhouette Score、肘部法Elbow Method、WCSS/惯性Inertia与方差Variance等核心概念并逐步演示如何用 Scikit-learn 对 Spotify 尼日利亚音乐数据nigerian-songs.csv执行从箱线图探查、特征选择、标签编码到聚类建模、可视化和精度评估的完整流程。读完本文你将能独立使用 K-Means 对无标签数据分群并学会用轮廓系数与肘部法诊断聚类质量、识别高方差数据的局限性。课程背景与学习目标本节课程属于本仓库 5-Clustering 模块的第 2 课。在本课之前你已经完成了尼日利亚音乐数据的导入与初步清洗本课的目标是理解 K-Means 聚类的原理、适用条件与缺点掌握 4 个关键术语轮廓系数Silhouette scoring、肘部法Elbow method、惯性Inertia、方差Variance使用 notebook.ipynb 完成一次完整的无监督聚类实验学会用轮廓系数和肘部法评估k 取几最合适。正如上一课所学处理聚类问题的方法有很多具体选哪种取决于数据本身的形态而 K-Means 是最常用的一种因此本课首先对它进行实践。K-Means 聚类原理三步迭代的 Voronoi 划分K-Means 聚类 源于信号处理领域它用一系列观测样本把数据划分成 k 个簇每个样本被归入离它最近的均值簇中心点所在的簇。簇的几何形态可以用 Voronoi 图 来可视化每个种子点seed对应一片区域区域内任意一点到该种子的距离都小于到其他种子的距离。课程配套的示意图就直观展示了这种点 区域的划分方式信息图作者Jen LooperK-Means 的聚类过程在 Scikit-learn 官方文档 中被总结为三步从数据集中采样选出 k 个初始中心点进入迭代循环直到收敛把每个样本分配到最近的质心centroid取上一轮分配到各质心的所有样本的均值生成新的质心计算新旧质心的差异重复上述步骤直到质心不再移动稳定。K-Means 的一个明显缺点是你必须事先指定 k即质心的数量。幸运的是肘部法Elbow Method可以帮助你估计一个合理的初始 k 值——本课稍后会实际操作。从仓库的解决方案 notebook5-Clustering/2-K-Means/solution/notebook.ipynb可以看到完整的实现顺序先安装 seaborn、导入数据、过滤出 3 个主要流派再做箱线图检查离群值、选择特征列、训练 K-Means、计算轮廓系数、跑 WCSS 扫描、绘制肘部图、最终散点图与精度评估。接下来按步骤还原这一过程。数据准备从 nigerian-songs.csv 到 3 个目标流派课程的所有实验都在 notebook.ipynb 中展开。第一步是加载上一课已经完成初步清洗的数据import matplotlib.pyplot as plt import pandas as pd import seaborn as sns df pd.read_csv(../data/nigerian-songs.csv) df.head()说明主课 notebook 位于5-Clustering/2-K-Means/下因此数据路径为../data/nigerian-songs.csv而解决方案 notebook 位于solution/子目录对应路径为../../data/nigerian-songs.csv。随后把数据聚焦到 3 个主要流派为3 个簇的猜想做铺垫df df[(df[artist_top_genre] afro dancehall) | (df[artist_top_genre] afropop) | (df[artist_top_genre] nigerian pop)] df df[(df[popularity] 0)] top df[artist_top_genre].value_counts() plt.figure(figsize(10,7)) sns.barplot(xtop.index,ytop.values) plt.xticks(rotation45) plt.title(Top genres,color blue)从仓库中的真实数据文件 5-Clustering/data/nigerian-songs.csv530 行 × 16 列可以看到原始数据包含name、album、artist、artist_top_genre、release_date、length、popularity、danceability、acousticness、energy、instrumentalness、liveness、loudness、speechiness、tempo、time_signature等字段。其中artist_top_genre的分布高度不均衡afro dancehall有 328 首、afropop有 90 首、nigerian pop有 24 首另有 53 首标记为Missing。过滤后实际参与聚类的样本为 286 首解决方案 notebook 输出为 286 个样本聚焦到 afro dancehall、afropop、nigerian pop 三个流派。练习一用箱线图排查离群值并挑选特征12 列箱线图首先对数据列逐个调用boxplot()生成 12 个子图观察分布与离群值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课程提示虽然可以遍历数据集剔除离群值但那样会让数据变得非常稀少因此本课暂不删除而是选择合适列参与聚类。特征选择与 LabelEncoder 编码接下来的关键是挑选取值范围相近的列并把类别列artist_top_genre编码为数值否则 K-Means基于欧氏距离的算法无法处理字符串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包含 6 个特征artist_top_genre编码后、popularity、danceability、acousticness、loudness、energyy保留原始的流派标签先取原始字符串再经le.transform(y)编码用于后续与聚类结果比对从而计算准确率LabelEncoder会把afro dancehall、afropop、nigerian pop映射为 0/1/2 之类的整数且保证X与y使用同一套编码映射。注意在解决方案 notebook 中还预留了from sklearn.preprocessing import LabelEncoder, StandardScaler与scaler StandardScaler()/X scaler.fit_transform(X)的注释代码——这正是本课结尾挑战环节提到的数据缩放改进方向后面会详细讨论。设定 k3 并训练第一个模型已知数据集中包含 3 个音乐流派于是先尝试 k3from 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输出是一个 numpy 数组每个样本对应一个簇编号0、1 或 2。解决方案 notebook 的实际输出是类似array([2, 1, 2, 2, 2, ...], dtypeint32)的预测结果——但这些数字本身没有直观意义需要借助轮廓系数来量化聚类质量。轮廓系数衡量簇的紧致与分离用 sklearn 的 metrics 模块计算轮廓系数from sklearn import metrics score metrics.silhouette_score(X, y_cluster_kmeans) score轮廓系数Silhouette Score的取值范围是-1 到 1越接近1簇内部密实dense且与其他簇分离良好well-separated接近0簇之间相互重叠样本紧贴相邻簇的决策边界为负值样本可能被分配到了错误的簇。本课数据集得到的轮廓系数约为0.53解决方案 notebook 的精确输出为0.5466747351275563正好处于中间水平。这表明这组数据并不特别适合 K-Means 这种聚类方式但课程选择继续推进以演示完整的建模与评估流程。练习二构建模型与 WCSS 扫描为了用肘部法确定最优 k需要对 k1..10 逐一训练 K-Means并记录每次的inertia_惯性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)聚类过程的迭代次数即尝试从 1 到 10 个簇为肘部法收集数据点。random_stateScikit-learn 官方文档指出它决定质心初始化时随机数的生成。固定该值可以保证结果可复现便于对比实验本课训练模型时统一使用random_state42。WCSSWithin-Cluster Sums of Squares簇内平方和度量簇内所有点到簇质心距离的平方平均值衡量每个簇内部有多紧凑。Inertia惯性K-Means 算法的优化目标就是选择质心以最小化惯性即簇在内部有多一致的度量。kmeans.inertia_就是当前 k 值下所有簇的 WCSS 之和每轮迭代追加到wcss列表中供后续画图。k-meansScikit-learn 支持的质心初始化优化策略它通常让初始质心彼此相距较远从而得到比完全随机初始化更好的结果。肘部法用 WCSS 曲线找到拐点既然目标是 3 个流派是不是就该选 k3用肘部法来验证一下。基于上一步累积的wcss列表绘图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()肘部法的思路随着 k 增大WCSS簇内平方和必然下降但下降速度会在某个点之后明显放缓曲线呈现手肘般的拐点bend/kink。拐点对应的 k 就是性价比最高的簇数量——再增加簇带来的收益骤减。从本课的肘部图看拐点确实出现在3附近印证了最初的猜想。练习三显示聚类结果并评估精度散点图观察簇的形态用 k3 重新训练并把聚类标签画成散点图横轴 popularity纵轴 danceabilityfrom 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)))解决方案 notebook 的真实输出为Result: 109 out of 286 samples were correctly labeled. Accuracy score: 0.380.38 的精度并不理想。为什么课程给出了三个原因数据太不均衡imbalanced3 个流派的样本量差距悬殊328 vs 90 vs 24特征间相关性太低little correlated所选列之间缺乏足够的关联结构列之间的方差太大too much variance各列数值范围差异大直接做欧氏距离会被大尺度列主导。实际上形成的簇很可能被我们预先定义的三个流派类别强烈影响甚至带偏——这正是聚类学习中常见的教训。Scikit-learn 文档中的示意图展示了这类簇边界不清的问题模型本质是方差问题信息图来自 Scikit-learn方差聚类效果不佳的根源方差Variance的定义是各数值与均值之差的平方的平均值。在本课的聚类语境下它指的是数据集中的数值偏离均值太多。K-Means 依赖欧氏距离如果某些特征列的方差远大于其他列它们会在距离计算中占据主导地位导致聚类被这些高方差列绑架。这也是一个思考如何改进的绝佳时机继续微调数据换用不同的特征列或者换一个聚类算法提示尝试对数据进行缩放标准化以归一化量纲并尝试其他特征组合。挑战通过缩放与清洗改进聚类课程的 挑战环节建议在 notebook 中花时间调整参数尝试回答能否通过更彻底的数据清洗例如剔除离群值提高模型精度能否用权重weights让某些样本更重要还有什么办法能生成更好的簇关键提示是对数据进行缩放。notebook 中有一段被注释掉的代码用标准缩放StandardScaler让各列在数值范围上更接近。你会发现一个反直觉的现象轮廓系数下降肘部图上的拐点被抹平kink smooths out。原因在于不缩放数据时方差较小的列反而携带了更多权重因为方差大的列主导了距离度量一旦缩放所有列被平等对待轮廓系数随之变化而 WCSS 曲线的拐点也不再那么锐利。这组数据在未经缩放时对 k3 给出了一个看似明确的肘部但那很可能是被高方差列制造出来的假象。关于均值归一化与特征缩放对 K-Means 的必要性可以进一步阅读相关统计学讨论也可以在 5-Clustering/2-K-Means/solution/notebook.ipynb 中直接看到StandardScaler的注释代码位置自行取消注释对比效果。作业尝试不同的聚类方法课程配套作业assignment.md要求既然 K-Means 有时并不适合某些数据请新建一个 notebook使用本课程数据或其他来源数据并注明来源演示一种非 K-Means 的聚类方法并总结你学到了什么。评分标准如下标准优秀Exemplary合格Adequate待改进Needs Improvement整体提交一个文档完备的聚类模型 notebook提交了 notebook 但缺乏良好文档或内容不完整提交不完整复习与自测可以使用在线 K-Means 模拟器来直观体验它允许你调整数据的随机性、簇的数量和质心数量观察样本点如何被分组、质心如何移动帮助建立对聚类过程的直觉。也可以参考斯坦福大学 CS221 课程关于 K-Means 的讲义深入理解算法推导与收敛性。小结本课完整走通了数据探查 → 特征选择 → K-Means 建模 → 轮廓系数评估 → 肘部法选 k → 可视化与精度对比的无监督聚类全流程并用真实数据nigerian-songs.csv验证了 K-Means 的适用边界轮廓系数 0.53 说明数据与 K-Means 的契合度一般肘部法确认 k3 相对合理但精读精度仅 0.38根源在于数据不均衡、特征相关性低、列间方差过大——这类问题提示我们考虑特征缩放、清洗离群值或换用其他聚类算法。相关资源都在仓库内可继续深入研究notebook.ipynb主课练习、solution/notebook.ipynb带运行输出的完整解答、solution/tester.ipynb测试环境以及同目录下的 R 语言实现5-Clustering/2-K-Means/solution/R/lesson_15-R.ipynb 与 lesson_15.Rmd。下一课将继续探索其他聚类可视化与算法建议先完成作业中的非 K-Means 聚类对比实验再进入下一阶段。说明本文基于 ML-For-Beginners 课程第 15 课《K-Means 聚类》整理数据与代码均来自本仓库 5-Clustering/2-K-Means 目录轮廓系数与精度等数值取自解决方案 notebook 的真实运行输出。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考