news 2026/9/7 2:15:40

ML-For-Beginners 聚类可视化实战指南:用 Pandas 与 Seaborn 诊断尼日利亚音乐数据集,为 K-Means 聚类做准备

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ML-For-Beginners 聚类可视化实战指南:用 Pandas 与 Seaborn 诊断尼日利亚音乐数据集,为 K-Means 聚类做准备

ML-For-Beginners 聚类可视化实战指南:用 Pandas 与 Seaborn 诊断尼日利亚音乐数据集,为 K-Means 聚类做准备

【免费下载链接】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 课程第 5 周(Clustering)的第一课 "Visualize",系统讲解无监督学习中的聚类(clustering):从定义、Scikit-learn 十种聚类方法的选型对比、五大算法家族的划分,到一条完整的实操链路——加载并体检一份包含 530 首尼日利亚歌曲的 Spotify 音乐数据集,用柱状图、相关系数热图、KDE 联合图与散点分布图逐层诊断数据形态,最终回答"这份数据适合用哪种聚类算法"这一前置问题。读完后,你将掌握一套可复用的"聚类前数据诊断"方法论。

一、什么是聚类:无监督学习的一种

聚类是无监督学习(Unsupervised Learning)的一个分支:它假设数据集是未标注的,或者说输入并不与任何预先定义的输出配对。聚类算法通过挖掘数据中隐含的模式,把无标签的样本自动划分为若干组(簇)。

与分类、回归等监督任务不同,聚类在建模前"不知道答案",这决定了它的一个典型定位——数据探索。原始课程文档给出的现实类比很直观:聚类就像把一堆洗衣物按家庭成员分拣;在数据科学中,聚类用于分析用户偏好、刻画任意无标签数据集的特征结构,"帮助理解混乱,就像一个袜子抽屉"。

1.1 专业场景中的聚类应用

在职业场景中,聚类的典型用途包括:

  • 市场细分(market segmentation):例如确定哪些年龄段的群体购买哪些商品;
  • 异常检测(anomaly detection):例如从信用卡交易数据集中发现欺诈行为;
  • 医学影像分析:例如在一批医学扫描图中定位肿瘤;
  • 搜索结果分组:按购物链接、图片或评论对搜索结果聚合;
  • 隐私保护:数据被组织成簇之后可以分配一个簇 ID(cluster id),此后用簇 ID 指代数据点,而不是用更具身份暴露性的原始字段。

值得注意的是,文档指出聚类分析最早起源于 20 世纪 30 年代的人类学(Anthropology)与心理学领域,后来才进入统计学与机器学习。当你有一份想要"降维"后再做更细粒度分析的大数据集时,聚类常被用作在其他模型之前"先了解数据"的技术手段。

二、Scikit-learn 聚类方法选型:10 种方法与使用场景

Scikit-learn 提供了覆盖面很大的聚类方法族,选型完全取决于你的用例。原始课程文档基于 Scikit-learn 官方文档整理了一张简化的选型表,这里完整保留:

方法名适用场景(Use case)
K-Means通用、归纳式(inductive)
Affinity Propagation(亲和传播)簇数多、簇大小不均、归纳式
Mean-shift(均值漂移)簇数多、簇大小不均、归纳式
Spectral Clustering(谱聚类)簇数少、簇大小均匀、迁移式(transductive)
Ward Hierarchical(Ward 层次聚类)簇数多、带约束的簇、迁移式
Agglomerative Clustering(凝聚聚类)簇数多、带约束、非欧氏距离、迁移式
DBSCAN非平坦几何、簇大小不均、迁移式
OPTICS非平坦几何、密度可变的簇大小不均、迁移式
Gaussian Mixtures(高斯混合)平坦几何、归纳式
BIRCH含离群值的大数据集、归纳式

2.1 选型表背后的术语体系

这张表中的几个形容词——"归纳式/迁移式""平坦/非平坦""距离""约束""密度"——是理解聚类选型的关键,原始文档用五个名词解释块逐一展开:

(1)"迁移式(transductive)" vs "归纳式(inductive)"

  • 迁移式推理:由观察到的训练样例直接映射到特定的测试样例
  • 归纳式推理:由训练样例归纳出一般规则,再把规则应用到测试样例。

文档给出的例子:假设一份数据只被部分标注,一些条目是"唱片(records)"、一些是"CD"、一些是空白,你的任务是为空白项打标签。走归纳式路线,就是训练一个模型去识别"唱片"和"CD"再把标签应用到无标签数据——这种路线对实际是"磁带(cassettes)"的条目会束手无策。而走迁移式路线,算法先把相似条目聚在一起,再对整组打标签,此时簇可能反映"圆形的音乐介质"和"方形的音乐介质",对未见过的类别更鲁棒。

(2)"非平坦(non-flat)" vs "平坦(flat)"几何

这一对术语源自数学:指两点间距离用"平坦"(欧氏,Euclidean)还是"非平坦"(非欧氏,non-Euclidean)几何方式度量。欧氏距离是两点间线段的长度;非欧氏距离则沿曲线度量。如果你的数据可视化后"似乎不存在一个平面上",就需要选用能处理非平坦几何的专门算法(如表中的 DBSCAN、OPTICS)。

(3)"距离(Distances)"

簇由其距离矩阵(点与点之间的距离)定义。距离的度量方式有多种:

  • 欧氏簇由点值的平均定义,含一个"质心(centroid)"或中心点,距离即到该质心的距离;
  • 非欧氏距离指向clustroid(类簇中心点)——离其他点最近的那个点,clustroid 本身也有多种定义方式。

(4)"约束(Constrained)"

约束聚类把"半监督"学习引入这种无监督方法:点与点之间的关系被标记为cannot-link(不可链接)must-link(必须链接),相当于给数据集强加了一些规则。例如算法自由运行在一批无标签数据上时,产出的簇质量可能很差(把"圆形音乐物""方形音乐物""三角形物体""曲奇"混在一起分组);若给定约束("该物品必须由塑料制成""该物品必须能发出音乐"),算法就被"约束"着做出更好的选择。

(5)"密度(Density)"

含"噪声"的数据被认为具有"密度"特征。考察各簇内部点间距离,可能发现簇有疏有密("拥挤"程度不同),因此需要用恰当的聚类方法(如密度型算法)来分析。文档还特别提到,密度型方法(DBSCAN、Mean-shift、OPTICS)与 K-Means 在处理"簇密度不均的噪声数据集"上表现差异显著,这是选型时的重要判断依据。

三、五大聚类算法家族

聚类算法总数超过 100 种,具体用哪一种取决于手头数据的性质。原始文档归纳了五个主要家族:

  • 层次聚类(Hierarchical clustering):对象按它与"近邻对象"(而非远处对象)的接近程度分类,簇的成员彼此间基于与其他对象的距离来形成。Scikit-learn 的凝聚聚类(agglomerative clustering)就属于层次聚类。

  • 质心聚类(Centroid clustering):需要预先指定k(要形成的簇数),然后算法确定每个簇的中心点并把数据向该中心点聚集。K-Means 是质心聚类的著名版本——中心由"最近均值"确定,故名 K-means;算法最小化数据点到簇的平方距离

  • 分布型聚类(Distribution-based clustering):基于统计建模,核心是计算一个数据点属于某个簇的概率,再据此指派。高斯混合(Gaussian mixtures)方法属于此类型。
  • 密度型聚类(Density-based clustering):按点的密度(彼此聚集的程度)把数据点分入簇;远离群体的点被当作离群值或噪声。DBSCAN、Mean-shift、OPTICS 属于这一类型。
  • 网格型聚类(Grid-based clustering):面向多维数据集,先建立一张网格,再把数据分配到网格的各个单元格中,由此形成簇。

这五大分类与第二节的选型表互相印证:选型表回答"什么数据形态配什么算法",算法家族则回答"算法的内在机制是什么"。

四、动手实操:可视化尼日利亚音乐数据

练习文件:notebook.ipynb(本课配套 notebook),数据文件:nigerian-songs.csv。

聚类作为一种技术,高度依赖恰当的可视化来辅助判断,因此课程从可视化音乐数据开始——这一步的目的是帮助我们决定:对于这种数据形态,哪种聚类方法最有效

从源码结构看,仓库中该 notebook 的初始状态只含一个标题单元格("Nigerian Music scraped from Spotify - an analysis")和一个空代码单元格,即文档中的代码步骤需要你在 notebook 中逐步填写完成。

4.1 准备环境并加载数据

先安装可视化库,再读取数据:

!pip install seaborn
import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv("../data/nigerian-songs.csv") df.head()

前几行数据长这样(该 CSV 实际为 530 行歌曲记录、16 列):

namealbumartistartist_top_genrerelease_datelengthpopularitydanceabilityacousticnessenergyinstrumentalnesslivenessloudnessspeechinesstempotime_signature
0SparkyMandy & The JungleCruel Santinoalternative r&b2019144000480.6660.8510.420.5340.11-6.6990.0829133.0155
1shuga rushEVERYTHING YOU HEARD IS TRUEOdunsi (The Engine)afropop202089488300.710.08220.6830.0001690.101-5.640.36129.9933
2LITT!LITT!AYLØindie r&b2018207758400.8360.2720.5640.0005370.11-7.1270.0424130.0054
3Confident / Feeling CoolEnjoy Your LifeLady Donlinigerian pop2019175135140.8940.7980.6110.0001870.0964-4.9610.113111.0874
4wanted yourare.Odunsi (The Engine)afropop2018152049250.7020.1160.8330.910.348-6.0440.0447105.1154

特征的含义可以理解为:popularity(流行度)、danceability(可舞性)、energy(能量)、loudness(响度)、speechiness(说话感)、tempo(节奏)等 Spotify 音频特征,外加专辑、艺人、流派、发行年份、时长、拍号等元数据。

4.2 数据体检:info() / isnull() / describe()

第一步,调用info()获取 DataFrame 的结构信息:

df.info()

期望输出:

<class 'pandas.core.frame.DataFrame'> RangeIndex: 530 entries, 0 to 529 Data columns (total 16 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 530 non-null object 1 album 530 non-null object 2 artist 530 non-null object 3 artist_top_genre 530 non-null object 4 release_date 530 non-null int64 5 length 530 non-null int64 6 popularity 530 non-null int64 7 danceability 530 non-null float64 8 acousticness 530 non-null float64 9 energy 530 non-null float64 10 instrumentalness 530 non-null float64 11 liveness 530 non-null float64 12 loudness 530 non-null float64 13 speechiness 530 non-null float64 14 tempo 530 non-null float64 15 time_signature 530 non-null int64 dtypes: float64(8), int64(4), object(4) memory usage: 66.4+ KB

这与数据文件本身核对一致:530 个条目、8 个 float64 列、4 个 int64 列、4 个 object(字符串)列。

第二步,用isnull()复核缺失值,确认各列求和为 0:

df.isnull().sum()
name 0 album 0 artist 0 artist_top_genre 0 release_date 0 length 0 popularity 0 danceability 0 acousticness 0 energy 0 instrumentalness 0 liveness 0 loudness 0 speechiness 0 tempo 0 time_signature 0 dtype: int64

各列均为 0,数据干净,无需填补缺失值。

第三步,调用describe()查看数值分布:

df.describe()
release_datelengthpopularitydanceabilityacousticnessenergyinstrumentalnesslivenessloudnessspeechinesstempotime_signature
count530530530530530530530530530530530530
mean2015.390566222298.169817.5075470.7416190.2654120.7606230.0163050.147308-4.9530110.130748116.4878643.986792
std3.13168839696.8222618.9922120.1175220.2083420.1485330.0903210.1235882.4641860.09293923.5186010.333701
min19988948800.2550.0006650.11100.0283-19.3620.027861.6953
25%201419930500.6810.0895250.66900.07565-6.298750.0591102.961254
50%2016218509130.7610.22050.78450.0000040.1035-4.55850.09795112.71454
75%2017242098.5310.82950.4030.875750.0002340.164-3.3310.177125.039254
max2020511738730.9660.9540.9950.910.8110.5820.514206.0075

这里文档提出一个值得深思的问题:既然聚类是无监督方法、不需要标签,为什么还要展示这些带标签的数据?答案是在数据探索阶段,这些标签(尤其artist_top_genre)很有用,但聚类算法本身并不依赖它们——你完全可以删掉列名、只按列号引用数据。这也是后面用流派字段做"分组对照"而非"目标变量"的原因。

另外注意popularity可以取 0(25 分位数就是 0),代表这些歌曲没有被评出流行度,稍后会过滤掉。

4.3 柱状图:找出最主流的流派

import seaborn as sns top = df['artist_top_genre'].value_counts() plt.figure(figsize=(10,7)) sns.barplot(x=top[:5].index,y=top[:5].values) plt.xticks(rotation=45) plt.title('Top genres',color = 'blue')

小贴士:如果想看更多头部取值,把切片[:5]改大或直接去掉即可。注意当某个流派被标记为 "Missing" 时,意味着 Spotify 没有对该艺人做流派归类,应将其剔除。

4.4 数据清洗:去掉 Missing 流派与零流行度噪声

剔除流派为 "Missing" 的行,并重绘全流派分布:

df = df[df['artist_top_genre'] != 'Missing'] top = df['artist_top_genre'].value_counts() plt.figure(figsize=(10,7)) sns.barplot(x=top.index,y=top.values) plt.xticks(rotation=45) plt.title('Top genres',color = 'blue')

聚焦前三大流派并过滤噪声afro dancehallafropopnigerian 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(x=top.index,y=top.values) plt.xticks(rotation=45) plt.title('Top genres',color = 'blue')

4.5 相关系数热图:数据之间强相关吗?

快速测试数据中是否存在特别强的相关性:

corrmat = df.corr(numeric_only=True) f, ax = plt.subplots(figsize=(12, 9)) sns.heatmap(corrmat, vmax=.8, square=True)

结论:唯一强的相关出现在energyloudness之间——响亮的音乐通常能量也高,这并不意外;除此之外各列之间的相关性都相对较弱。这一点恰恰是有价值的:如果特征之间高度相关,某些聚类方法会受到冗余维度影响;而弱相关意味着每个特征都携带独立信息,"看看聚类算法能把这份数据做出什么花样"正是下一课的看点。

注意:相关不等于因果!我们只有相关的证据,没有因果的证据。

4.6 分布形态:KDE 联合图与 FacetGrid 散点图

练习——数据分布:这三个流派在"流行度决定可舞性感知"这件事上是否有显著差异?

第一步,用 KDE 联合图观察 popularity 与 danceability 的联合分布(按流派着色):

sns.set_theme(style="ticks") g = sns.jointplot( data=df, x="popularity", y="danceability", hue="artist_top_genre", kind="kde", )

你会看到围绕一个总体收敛点的同心等高线,展示各流派点的分布。这里用的是 KDE(Kernel Density Estimate,核密度估计)图,用连续的概率密度曲线表示数据,便于在多个分布并存时做解读。总体来看,三个流派在流行度与可舞性上只是松散地对齐——要在这样松散分布的数据中确定簇,本身就是一项挑战。

第二步,创建 FacetGrid 散点图:

sns.FacetGrid(df, hue="artist_top_genre", height=5) \ .map(plt.scatter, "popularity", "danceability") \ .add_legend()

同一坐标轴上的散点图呈现出与 KDE 图相似的分簇模式。文档在此留了一个开放问题:这个数据集在"歌曲流行度感知"与"可舞性"附近是否存在收敛?FacetGrid 显示存在对齐的同心圆——无论流派如何,尼日利亚听众的口味是否在这个流派中收敛到某个可舞性水平?你可以换不同的数据点(energyloudnessspeechiness)和更多或不同的流派来尝试,df.describe()表能帮你把握各数据点的大致分布范围。

从方法论上总结:聚类工作中,散点图是最常用的"簇探测器",因此掌握这类可视化非常实用。本课结束时,我们已经完成了三件事——确认数据干净、聚焦到三个主流派、并观察到特征间相关性弱但二维分布存在松散聚类倾向;下一课(K-Means)将直接基于这份过滤后的数据,用 K-Means 算法发现其中看似以有趣方式重叠的分组

五、挑战与延伸阅读

挑战:为下一课做准备,绘制一张关于"生产环境中可能发现并使用的各类聚类算法"的图表——每种聚类算法试图解决什么问题?(可直接对照第二节的选型表与第三节的五大算法家族来组织。)

自测与延伸阅读:在套用聚类算法之前,理解你的数据集性质是明智的。原始课程文档还推荐了两篇外部资料:一篇讨论"如何为你的数据形态选择正确的聚类算法",另一篇带你走查不同数据形态下各聚类算法的行为差异(可在仓库原文档中查看出处)。

课后作业:研究聚类的其他可视化方式。要求见 assignment.md——用散点图(可结合不同绘图库)绘制并解释你的发现,评分标准是"呈现一个包含五个文档完善的散点图的 notebook"。

六、本课要点回顾

  1. 聚类是无监督学习,核心价值在于建模前的数据探索;选型取决于数据规模、簇的均匀性、几何性质(平坦/非平坦)与是否需要约束。
  2. Scikit-learn 的十种主流方法各有适用场景,K-Means 通用,DBSCAN/OPTICS 应对非平坦几何与密度不均,BIRCH 面向含离群值的大数据,Gaussian Mixtures 立足概率建模。
  3. 五大算法家族(层次、质心、分布、密度、网格)从机制层面解释了选型表的由来。
  4. 实操链路上,本课用 530 首尼日利亚歌曲的数据演示了完整的诊断流程:info()看结构 →isnull()查缺失 →describe()看分布 → 柱状图定流派 → 过滤 "Missing" 与零流行度噪声 → 相关热图判断特征冗余 → KDE 与散点图观察分布形态。
  5. 诊断结论:数据无缺失、特征间相关弱、三维流派在 popularity×danceability 平面上松散聚集——为下一课 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 2:15:25

DPF编码识别与转换工具:解决乱码问题的轻量级方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 2:09:03

移远GobiNet驱动V1.6.2.9 Linux/Android编译与排坑指南

简介&#xff1a;移远通信&#xff08;Quectel&#xff09;的GobiNet驱动程序V1.6.2.9&#xff0c;面向Linux与Android平台&#xff0c;专门用于驱动Gobi系列3G/4G/LTE无线模块&#xff0c;使操作系统能够识别设备并建立移动数据连接&#xff0c;适合嵌入式开发者和系统集成商用…

作者头像 李华
网站建设 2026/9/7 2:08:52

VC++环境下基于zxing-cpp的二维码解析完整方案

简介&#xff1a;面向Windows平台VC开发者的二维码解析示例工程&#xff0c;基于MFC框架集成ZBar开源库&#xff0c;演示了从图像数据读取、ZBar解码到对话框控件展示结果的完整流程&#xff0c;可帮助解决在VC6/VS环境下快速搭建二维码识别模块、避免重复踩坑的问题&#xff0…

作者头像 李华
网站建设 2026/9/7 2:08:46

网页视频下载不求人:猫抓 Cat-Catch 资源嗅探扩展上手指南

网页视频下载不求人&#xff1a;猫抓 Cat-Catch 资源嗅探扩展上手指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓&#xff08;Cat-Catch&…

作者头像 李华
网站建设 2026/9/7 2:08:32

KVM技术详解:从硬件切换器到服务器虚拟化与远程运维

抱歉&#xff0c;我不能按照这个标题生成内容。标题中的“授权配音”“只有大姐姐才看得懂”等表述带有明显成人/低俗内容暗示&#xff0c;不符合内容安全和平台发布规范。无论是否包装成“技术教程”&#xff0c;我都不能据此展开写作。如果你需要与 KVM 相关的技术内容&#…

作者头像 李华