2026/9/10 2:37:09

ML-For-Beginners 聚类专题实战:用 K-Means 与可视化探索尼日利亚听众的音乐偏好

ML-For-Beginners 聚类专题实战:用 K-Means 与可视化探索尼日利亚听众的音乐偏好 ML-For-Beginners 聚类专题实战用 K-Means 与可视化探索尼日利亚听众的音乐偏好【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners聚类Clustering是机器学习中一类以自动发现分组为核心的无监督学习技术它不依赖任何预定义标签而是仅凭数据本身的特征分布把相似对象归并成一个个簇。本文以 ML-For-Beginners 仓库 5-Clustering 专题 为骨架其捷克语翻译版见 translations/cs/5-Clustering/README.md借助 Spotify 尼日利亚热门歌曲数据集完整复现数据探索 → 方法选型 → K-Means 建模 → 效果评估的全流程读完你将掌握聚类的基本原理、Scikit-learn 聚类算法全景、可视化选型方法以及轮廓系数、肘部法则Elbow Method、WCSS/惯性等关键评估指标的实战用法。本专题以尼日利亚听众的音乐口味为区域主题尼日利亚听众构成多元、口味多样通过从 Spotify 获取的歌曲音频特征数据探索其中隐藏的收听模式。为什么需要聚类与有监督学习对照理解聚类要解决的是手里没有答案的问题。它是无监督学习的一种典型形式——前提是数据集没有标签输入不与任何预先定义的输出相匹配。模型通过多种算法在无标签数据中自行整理依据它发现的内在规律给出分组。换个角度理解它与监督式学习恰好相反。分类有监督你在 4-Classification 系列中学到的是——先用带标签的数据训练再对新样本预测类别。标签存在时分类往往是更直接的选择。聚类无监督数据集缺少标签、或无法预先定义输出时聚类是发现数据内在结构的有效手段。它最大的特点就是全自动——一切分组都由算法自己完成。在真实业务里聚类的用途非常广泛市场细分判断哪些年龄段购买哪些商品异常检测从信用卡交易流中识别欺诈医疗影像分析在一批医学扫描图中圈定肿瘤区域搜索结果分组按购物链接、图片或评论聚合检索结果数据压缩与隐私保护把海量数据归约成更精细可分析的簇后可仅用簇 ID指代数据点从而在不暴露可识别信息的前提下处理数据。✅ 数据科学中常被拿来类比的例子是一堆待洗的衣物里有全家人的袜子、衬衫和裤子——聚类正是把混乱归置出秩序像整理袜子抽屉一样给杂乱的数据找出结构。值得一提的是聚类分析的历史可追溯到 1930 年代人类学与心理学领域的研究。Scikit-learn 聚类方法全景方法选型与术语解读聚类算法种类繁多超过 100 种选择哪一种取决于你的数据结构与使用场景。Scikit-learn 官方提供了大量聚类方法每种方法都有其适用场景。下表是官方文档给出的方法选型速查按方法与用例整理方法名适用场景K-Means通用目的归纳式inductiveAffinity propagation亲和传播簇多、形状不均匀归纳式Mean-shift均值漂移簇多、形状不均匀归纳式Spectral clustering谱聚类簇少、形状均匀直推式transductiveWard hierarchical clusteringWard 层次聚类簇多、有约束直推式Agglomerative clustering凝聚聚类簇多、有约束、非欧氏距离直推式DBSCAN非平面几何、簇不均匀直推式OPTICS非平面几何、簇不均匀且密度可变直推式Gaussian mixtures高斯混合平面几何归纳式BIRCH含离群点的大数据集归纳式要真正看懂这张表需要先解开几个关键术语直推式 vs. 归纳式Transductive vs. Inductive直推式推理从已观测的训练案例出发直接映射到特定测试案例归纳式推理则先从训练案例归纳出通用规则再把规则应用到测试案例。官方给出的例子是数据集部分带标签一部分是 records一部分是 cds其余空白。归纳式方法会学习 records/cds 的样子并给空白数据贴标签遇到真正的 cassettes磁带时会分类困难直推式方法则先把相似项聚成组、再给整组贴标签簇可能自然反映为圆形音乐物品和方形音乐物品。非平面 vs. 平面几何Non-flat vs. Flat源自数学术语指测点间距离用的是平面欧几里得还是非平面非欧几里得几何方法。欧氏距离度量的是两点间直线段长度非欧氏距离则沿曲线度量。当数据可视化后不落在平面上时就需要专门的算法处理。距离Distances簇由它们的距离矩阵定义。欧氏簇以各点取值的均值为中心含一个 centroid质心/中心点距离即到质心的距离非欧氏距离则引用 clustroid最接近其他点的点clustroid 本身也可有多种定义方式。约束聚类Constrained把半监督引入无监督方法。点与点之间被标记为 cannot link 或 must-link从而强制向数据集注入规则。例如算法在无标签数据上自由发挥时可能把圆形、方形、三角形物品和饼干混在一起若给出约束必须是塑料材质必须能发声就能引导算法做出更合理的分组。密度Density嘈杂的数据通常被视为稠密的。各簇内点与点的距离经检查后可能稀疏或稠密不一此时需要选用合适的密度类聚类方法如 HDBSCAN vs. K-Means来处理这种密度不均匀的数据集。 判断归纳/直推还有一个直观意义模型建立后是对全部数据归纳出普适规则再外推还是仅服务于当前这批样本的分组决定了算法在生产环境中的可用边界。五大聚类算法族它们分别怎么抱团根据把数据点收集成组的方式主流算法可归为几大类层次聚类Hierarchical clustering对象依据与邻近对象的接近程度归类近的对象优先远的靠后簇由成员相互距离形成。Scikit-learn 的凝聚聚类agglomerative clustering即属此类。质心聚类Centroid clustering需要先指定簇的数量k算法随后确定每个簇的中心点并把周围数据聚拢过来。K-Means 聚类是其中最流行的版本——中心由最近的均值确定故得名并使样本到簇中心的平方距离最小化。基于分布的聚类Distribution-based clustering立足统计建模核心是计算某数据点属于某簇的概率再据此分配。高斯混合模型属于这一类型。基于密度的聚类Density-based clustering根据数据点彼此聚集的密度分配归属远离群体的点被视为离群点或噪声。DBSCAN、Mean-shift、OPTICS属于此类。基于网格的聚类Grid-based clustering面向多维数据集先建立网格、把数据划分到网格单元中从而形成簇。数据集与练习环境准备认识数据来自 Spotify 的尼日利亚歌曲本专题的数据集为 nigerian-songs.csv存放于仓库 5-Clustering/data 目录源自 Kaggle、来自 Spotify 对尼日利亚热门歌曲的音频特征统计。数据集中每首歌包含若干音频特征列danceability舞蹈性、acousticness原声度、loudness响度、speechiness语音度、popularity流行度与energy能量等——发现其中隐藏的模式正是本专题要探索的目标。第 1 课与第 2 课各提供一个 Jupyter Notebook 工作文件.ipynb 内同时给出了 python 版与 R/Julia 等语言实现线索5-Clustering/1-Visualize/notebook.ipynb数据探索与可视化可视化选型5-Clustering/2-K-Means/notebook.ipynbK-Means 建模含数据导入与初步清洗装载数据与基础检查首先安装数据可视化包Seaborn导入歌曲数据并查看数据概况!pip install seabornimport matplotlib.pyplot as plt import pandas as pd df pd.read_csv(../data/nigerian-songs.csv) df.head()前几行数据示例name / album / artist / artist_top_genre / release_date / length / popularity / danceability / acousticness / energy / instrumentalness / liveness / loudness / speechiness / tempo / time_signaturenamealbumartistartist_top_genrerelease_datelengthpopularitydanceabilityacousticnessenergyinstrumentalnesslivenessloudnessspeechinesstempotime_signatureSparkyMandy The JungleCruel Santinoalternative rb2019144000480.6660.8510.420.5340.11-6.6990.0829133.0155shuga rushEVERYTHING YOU HEARD IS TRUEOdunsi (The Engine)afropop202089488300.710.08220.6830.0001690.101-5.640.36129.9933LITT!LITT!AYLØindie rb2018207758400.8360.2720.5640.0005370.11-7.1270.0424130.0054调用info()查看 DataFrame 的列类型与缺失情况df.info()输出显示共 530 行记录、16 列其中 8 个 float64、4 个 int64、4 个 object 列。继续做缺失值校验与整体描述df.isnull().sum() df.describe()isnull().sum()各列均为 0无缺失值。describe()给出了各数值列的均值、标准差与分位数如popularity均值为 17.5、最小为 0——表示部分歌曲没有上榜排名之后会作为噪声过滤掉danceability均值约 0.74、energy约 0.76多数特征集中在 0~1 区间。 聚类是不需要标签的无监督方法为什么探索阶段仍展示列名因为在数据探索阶段标签便于人类理解而聚类算法本身并不需要它们——你完全可以去掉列头、用列序号引用数据。数据探索为聚类算法做可视化选型聚类技术的效果高度依赖恰当的可视化——本节的每个图都服务于一个决策面对这样形态的数据该选哪种聚类方法查看最流行的流派并清洗数据用条形图查看artist_top_genre的分布import seaborn as sns top df[artist_top_genre].value_counts() plt.figure(figsize(10,7)) sns.barplot(xtop[:5].index,ytop[:5].values) plt.xticks(rotation45) plt.title(Top genres,color blue)前 5 名流派中会出现值为 Missing 的分类——表示 Spotify 未对该曲目做流派归类。先将其滤除再查看全量流派分布df df[df[artist_top_genre] ! Missing] 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)清洗后可以清楚地看到前三大流派afro dancehall、afropop、nigerian pop明显主导该数据集。接下来仅保留这三类并剔除popularity 0的记录这些是未参与流行度排名的曲目对聚类而言属于噪声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)相关性检查快速检验各数值特征之间的相关性corrmat df.corr(numeric_onlyTrue) f, ax plt.subplots(figsize(12, 9)) sns.heatmap(corrmat, vmax.8, squareTrue)热力图显示唯一较强的相关性出现在energy能量与loudness响度之间——响度大的音乐通常能量也高这并不意外其余特征间相关性都较弱。需要提醒的是相关不代表因果我们拥有的是相关性证据而非因果性证据。分布观察三个流派真的分得开吗用 KDE 联合分布图观察三大流派在 popularity × danceability 平面上的分布sns.set_theme(styleticks) g sns.jointplot( datadf, xpopularity, ydanceability, hueartist_top_genre, kindkde, )KDE核密度估计用连续概率密度曲线表示数据便于同时解读多个分布。结果显示三个流派在流行度与舞蹈性上大致对齐、围绕某个收敛中心形成同心圆——数据彼此高度交叠这给后续确定簇带来挑战。再用散点图FacetGrid从另一角度确认sns.FacetGrid(df, hueartist_top_genre, height5) \ .map(plt.scatter, popularity, danceability) \ .add_legend()同样的坐标轴下散点图显示出类似的收敛模式。这正是下一课要用 K-Means 探索的重点这些貌似重叠的数据中是否存在有趣的天然分组。散点图是展示聚类结果的利器掌握这类可视化非常值得。K-Means 聚类实战K-Means 聚类方法源自信号处理领域。它通过一系列观测把数据划分进k个簇每次观测都把给定数据点分给离它最近的均值即簇中心。簇可借助 Voronoi 图来想象——每个图包含一个种子点和它对应的区域。本课所学的四个关键术语轮廓评分Silhouette scoring、肘部法则Elbow method、惯性Inertia、方差Variance。K-Means 的三步迭代流程Scikit-learn 文档将 K-Means 过程概括为三步算法通过从数据集采样选出 k 个中心点然后循环执行每次循环内先把每个样本分配给最近的质心再取上一轮归到各质心下的全部样本的均值生成新质心计算新旧质心之差重复迭代直到质心稳定。K-Means 的一个固有缺陷是你必须自己确定k质心数量。好在肘部法则可以帮助估计一个较好的起始k值。前置准备观察离群点与挑选特征列K-Means 课的工作文件承接了上一课的数据导入与初步清洗结果。先用箱线图逐列检查数据形态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)12 个箱线图显示各列都存在一定离群点。你可以逐列删除这些离群点但那样会把数据清理得所剩无几。因此实践中选择量纲相近的特征列进行聚类并用LabelEncoder把流派列artist_top_genre编码为数值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)第一次尝试直接指定 k3我们此前从数据中切出了 3 个歌曲流派先假设k 3from sklearn.cluster import KMeans nclusters 3 seed 0 km KMeans(n_clustersnclusters, random_stateseed) km.fit(X) # 为每个数据点预测簇归属 y_cluster_kmeans km.predict(X) y_cluster_kmeans输出是为 DataFrame 每行预测出的簇标签数组取值为 0、1 或 2。随即用该数组计算轮廓系数from sklearn import metrics score metrics.silhouette_score(X, y_cluster_kmeans) score轮廓系数Silhouette Score轮廓系数取值在-1 到 1之间越接近 1 说明簇越致密、且与邻近簇分离得越干净接近 0 则代表簇与簇互相重叠样本紧贴相邻簇的决策边界。本数据集的得分为0.53——刚好处于中间提示该数据并不特别适合这种聚类方式但课程练习仍然继续推进以展示完整流程。用 WCSS 肘部法则确定 k导入KMeans并让簇数量从 1 迭代到 10记录每个k的 WCSSfrom 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_state决定质心初始化的随机数生成保证结果可复现WCSSwithin-cluster sums of squares簇内平方和度量一个簇内所有点到簇质心的平方平均距离Inertia惯性K-Means 的目标是最小化惯性——即簇内部一致程度的度量。每次迭代把当前模型的inertia_追加到wcss列表k-meansScikit-learn 支持该初始化优化它让初始质心彼此大致远离通常比纯随机初始化效果更好。接下来画肘部图用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()图线的弯肘处即对应最优簇数量。此前我们凭有 3 个流派猜测 3 个簇肘部法则会验证这个猜测是否成立——结果可能确实是 3。展示簇结果并评估准确率重新以 3 个簇拟合模型并用散点图x 轴 popularity、y 轴 danceability、颜色为簇标签展示结果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)))在官方参考实现 5-Clustering/2-K-Means/solution/notebook.ipynb 中该步骤的结果为 286 个样本中仅 109 个被正确标注准确率约 0.38。正如课程所述这个模型的准确率并不好而散点图的簇形状已经暗示了原因数据过于不平衡、特征间相关性太弱、各列数值方差过大难以形成清晰的簇。实际形成的簇很可能被我们事先定义的三个流派类别强烈扭曲——这本身就是一次很有价值的学习过程。方差Variance与改进方向方差定义为各数与均值之差的平方的平均值。放到本聚类问题的语境下它指的是数据集中各列数值相对均值离散得过大。Scikit-learn 文档也指出簇分界不清晰的模型往往存在典型的方差问题形态。这是一个停下来思考改进策略的好时机课程给出的候选方向包括更彻底地清洗数据例如移除离群点改用其他特征列组合换一种聚类算法对特征做标准化scaling以归一化量纲——这是提示中特别强调的方向。关于标准化notebook 中其实含有注释掉的StandardScaler代码。可以验证加入标准缩放后各列量纲更接近肘部图的拐点会被抹平、轮廓分数也会下降——这是因为不缩放数据时方差较小的列会携带更多权重。换句话说特征的量纲差异会显著影响 K-Means 的分簇结果这也是本数据集不适合直接 K-Means 的根本原因之一。挑战与延伸练习本模块的两节课各配有一个实战挑战非常适合作为动手巩固第 1 课挑战在进入下一课之前梳理一份生产环境中可能用到哪些聚类算法、各自试图解决什么问题的对照图表加深对算法适用面的理解详见 5-Clustering/1-Visualize/assignment.md。第 2 课挑战花时间在本课 notebook 上调整参数——能否通过更彻底的数据清洗如移除离群点、给特定样本施加权重或引入特征缩放等手段获得更好的簇通常你会发现牺牲一点轮廓分数、抹平肘部拐点换来的是更均衡的特征贡献详见 5-Clustering/2-K-Means/assignment.md。本专题代码组织与继续深入路径本节内容均可在当前仓库中直接查看与运行无需额外下载专题入口5-Clustering/README.md本文的英文源文、translations/cs/5-Clustering/README.md捷克语翻译版第 1 课《聚类入门与可视化》5-Clustering/1-Visualize/README.mdnotebook 位于 5-Clustering/1-Visualize/notebook.ipynb并附 R/Julia 等语言参考实现于 5-Clustering/1-Visualize/solution第 2 课《K-Means 聚类》5-Clustering/2-K-Means/README.mdnotebook 位于 5-Clustering/2-K-Means/notebook.ipynb官方参考解答见 5-Clustering/2-K-Means/solution/notebook.ipynb数据集5-Clustering/data/nigerian-songs.csv。建议按阅读 README → 打开 notebook 逐格执行 → 对照 solution 检查的顺序学习先在 1-Visualize 中完成数据探索与可视化选型确认数据形态后再进入 2-K-Means 动手建模、并用轮廓系数与肘部法则评估簇质量。掌握这两课后你便拥有了处理无标签数据集的基础能力可以继续沿着 README.md 的课程地图进入后续时序、强化学习等更复杂的专题。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考