Chapter 18
聚类介绍
聚类介绍
聚类是一种无监督学习,假设数据集是无标签的,或者其输入未与预定义输出匹配。它使用各种算法对无标签数据进行排序,并根据数据中察觉到的模式提供分组。
🎥 点击上方图片观看视频。在学习机器学习中的聚类时,欣赏一些尼日利亚舞厅音乐 —— 这是PSquare 2014年广受好评的一首歌曲。
课前测验
介绍
聚类对于数据探索非常有用。让我们看看它是否能帮助发现尼日利亚观众消费音乐的趋势和模式。
✅ 花一分钟思考聚类的用途。在现实生活中,当你有一堆洗好的衣服需要分拣家人衣物时,就发生了聚类 🧦👕👖🩲。在数据科学中,当试图分析用户偏好,或确定任何无标签数据集的特征时,就会用到聚类。从某种意义上说,聚类帮助理清混乱,就像整理袜子抽屉一样。
🎥 点击上方图片观看视频:MIT的John Guttag介绍聚类
在专业环境中,聚类可以用于确定市场细分,例如确定不同年龄段购买的商品。另一个应用是异常检测,比如从信用卡交易数据集中检测欺诈。或者你可以用聚类来确定一批医学扫描中的肿瘤。
✅ 花一分钟思考你在银行、电商或商业环境中如何遇到过聚类技术。
🎓 有趣的是,聚类分析最早源于20世纪30年代的人类学和心理学领域。你能想象它当时是如何被使用的吗?
或者,你可以用聚类来对搜索结果进行分组,比如购物链接、图片或评论。当你拥有一个大型数据集并希望减少维度、进行更细致的分析时,聚类非常有用。这种技术可以用来在构建其他模型之前了解数据。
✅ 一旦你的数据被组织成簇(clusters),你就会分配簇ID,这项技术在保护数据隐私时很有用;你可以用簇ID而不是更具揭示性的可识别数据来引用数据点。你能想到其他使用簇ID而非簇中其他元素来标识的原因吗?
通过这个学习模块加深对聚类技术的理解。
聚类入门
Scikit-learn提供多种执行聚类的方法。选择哪种取决于你的使用场景。根据文档,每种方法各有优点。这里是Scikit-learn支持的方法及其合适用例的简化表格:
| 方法名称 | 适用场景 |
|---|---|
| K-Means | 通用,归纳式 |
| 亲和传播(Affinity propagation) | 多个、不均匀簇,归纳式 |
| Mean-shift | 多个、不均匀簇,归纳式 |
| 谱聚类(Spectral clustering) | 少数、均匀簇,传导式 |
| Ward层次聚类 | 多个、受约束簇,传导式 |
| 凝聚式聚类(Agglomerative clustering) | 多个、受约束、非欧几里得距离,传导式 |
| DBSCAN | 非平坦几何、不均匀簇,传导式 |
| OPTICS | 非平坦几何、不均匀且密度可变簇,传导式 |
| 高斯混合(Gaussian mixtures) | 平坦几何,归纳式 |
| BIRCH | 大型数据集带异常值,归纳式 |
🎓 聚类的创建方式与如何将数据点归集到组密切相关。让我们解析一些术语:
传导推断源于观察训练案例直接映射到特定测试案例。归纳推断源于训练案例对应的通用规则,再应用于测试案例。
举例:假设你的数据集只有部分标签,有的标记为“唱片”,有的标为“CD”,有的为空白。你的任务是给空白项赋标签。若用归纳方法,训练模型识别“唱片”和“CD”,并把这些标签应用于无标签数据。此方法难以识别“磁带”等新类别。传导方法则通过聚类将相似项分组,再将标签应用于组,比如“圆形音乐物品”和“方形音乐物品”。
源自数学术语,非平坦和平坦几何指用“平坦”(欧氏)或“非平坦”(非欧氏)几何方法测量点间距离。
此处“平坦”指欧几里得几何(部分内容称为“平面”几何),非平坦则指非欧氏几何。几何如何与机器学习相关?作为数学基础的两个领域,必须有统一方式测量簇中点距,根据数据特性选择“平坦”或“非平坦”测量方式。欧氏距离是点间线段长度,非欧氏距离是沿曲线测量距离。若数据可视化为非平面空间,需用专门算法处理。

信息图由Dasani Madipalli提供
🎓 '距离'
簇由其距离矩阵定义,如点间距离。距离可通过多种方式测量。欧氏簇基于点值平均,含有“质心”或中心点,距离即为点到质心的距离。非欧氏距离指“簇核”(clustroid),是距离其他点最近的点。簇核定义多样。
🎓 '受约束'
受约束聚类将“半监督”学习引入无监督方法,点间关系标记为“不能链接”或“必须链接”,从而对数据集施加规则。
举例:若算法自由处理无标签或半标签数据,生成的簇质量可能较差。例如上例中簇可能分为“圆形音乐物品”、“方形音乐物品”、“三角形物品”和“饼干”。如果添加约束如“物品必须由塑料制成”,“物品必须能够发出音乐”,可帮助算法做出更优选择。
🎓 密度
噪声数据被视为“密集”的。其内部点间距离审查可显示簇的稠密度或“拥挤”程度,因此需用适当聚类方法分析。这篇文章演示了用K-Means与HDBSCAN算法探索具有不均簇密度的噪声数据的差异。
聚类算法
聚类算法有100多种,选用取决于数据特性。以下是一些主要算法:
-
层次聚类。若对象通过与近邻对象的接近性分类,而非远处对象,簇则基于其成员间距离形成。Scikit-learn的凝聚式聚类即为层次聚类。

信息图由Dasani Madipalli提供
-
质心聚类。此流行算法需指定“k”(簇数),算法随后确定每簇中心点,收集周边数据。K-means聚类是质心聚类的常见形式。中心点通过最邻近均值确定,故名。簇的平方距离被最小化。

信息图由Dasani Madipalli提供
-
基于分布的聚类。基于统计建模,通过确定数据点属于某簇的概率并进行分配。高斯混合方法属于此类。
-
基于密度的聚类。通过密度或点间集结区分簇。远离簇的点被视为异常或噪声。DBSCAN、Mean-shift和OPTICS属于此类聚类。
-
基于网格的聚类。对多维数据集构建网格,将数据划分到网格单元中,从而形成簇。
练习 - 对你的数据进行聚类
聚类技术大受益于合适的可视化,让我们先可视化音乐数据开始。本练习帮助我们决定哪种聚类方法最适合此数据特质。
-
打开本文件夹中的notebook.ipynb文件。
-
导入
Seaborn包以实现良好的数据可视化。python!pip install seaborn -
追加来自nigerian-songs.csv的歌曲数据。加载包含歌曲信息的数据框。准备好导入库并导出数据进行探索:
pythonimport 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_signature 0 Sparky Mandy & The Jungle Cruel Santino alternative r&b 2019 144000 48 0.666 0.851 0.42 0.534 0.11 -6.699 0.0829 133.015 5 1 shuga rush EVERYTHING YOU HEARD IS TRUE Odunsi (The Engine) afropop 2020 89488 30 0.71 0.0822 0.683 0.000169 0.101 -5.64 0.36 129.993 3 2 LITT! LITT! AYLØ indie r&b 2018 207758 40 0.836 0.272 0.564 0.000537 0.11 -7.127 0.0424 130.005 4 3 Confident / Feeling Cool Enjoy Your Life Lady Donli nigerian pop 2019 175135 14 0.894 0.798 0.611 0.000187 0.0964 -4.961 0.113 111.087 4 4 wanted you rare. Odunsi (The Engine) afropop 2018 152049 25 0.702 0.116 0.833 0.91 0.348 -6.044 0.0447 105.115 4 -
获取关于数据框的一些信息,调用
info():pythondf.info()输出如下所示:
output<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 -
通过调用
isnull()并验证和为0,进行空值的双重检查:pythondf.isnull().sum()一切正常:
outputname 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 -
描述数据:
pythondf.describe()release_date length popularity danceability acousticness energy instrumentalness liveness loudness speechiness tempo time_signature count 530 530 530 530 530 530 530 530 530 530 530 530 mean 2015.390566 222298.1698 17.507547 0.741619 0.265412 0.760623 0.016305 0.147308 -4.953011 0.130748 116.487864 3.986792 std 3.131688 39696.82226 18.992212 0.117522 0.208342 0.148533 0.090321 0.123588 2.464186 0.092939 23.518601 0.333701 min 1998 89488 0 0.255 0.000665 0.111 0 0.0283 -19.362 0.0278 61.695 3 25% 2014 199305 0 0.681 0.089525 0.669 0 0.07565 -6.29875 0.0591 102.96125 4 50% 2016 218509 13 0.761 0.2205 0.7845 0.000004 0.1035 -4.5585 0.09795 112.7145 4 75% 2017 242098.5 31 0.8295 0.403 0.87575 0.000234 0.164 -3.331 0.177 125.03925 4 max 2020 511738 73 0.966 0.954 0.995 0.91 0.811 0.582 0.514 206.007 5
🤔 如果我们正在使用聚类,作为一种不需要标签数据的无监督方法,为什么我们要用带标签的数据来展示呢?在数据探索阶段,标签很有用,但对于聚类算法的运行并非必需。你完全可以移除列标题,仅用列号来引用数据。
观察数据的一般值。注意,popularity 可能是‘0’,这说明歌曲没有排名。我们稍后会去除这些数据。
-
使用条形图查找最受欢迎的流派:
pythonimport 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 没有对其进行分类,我们应该去除这些数据。
-
通过过滤去除缺失数据
pythondf = 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 dancehall,afropop和nigerian pop,另外过滤掉流行度为0的记录(表示该数据未被分类为有流行度,可以视为噪声):pythondf = 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') -
快速测试数据是否存在特别强的相关性:
pythoncorrmat = df.corr(numeric_only=True) f, ax = plt.subplots(figsize=(12, 9)) sns.heatmap(corrmat, vmax=.8, square=True)
唯一显著的强相关是
energy和loudness,这并不令人惊讶,因为响亮的音乐通常很有能量。其他相关性相对较弱。观察聚类算法如何挖掘这些数据将会很有趣。🎓 请注意,相关性不代表因果关系!我们有相关性的证明,但没有因果关系的证明。这个有趣的网站中有一些图示强调了这一观点。
该数据集中是否存在在歌曲感知流行度和舞蹈性的某种趋同?一个 FacetGrid 显示,无论流派如何,都有同心圆的排列。难道尼日利亚人的口味对于这个流派的某个舞蹈性水平存在趋同?
✅ 尝试不同的数据点(energy,loudness,speechiness)和更多或不同的音乐流派。你能发现什么?看一下 df.describe() 表了解数据点的整体分布。
练习 - 数据分布
这三个流派在舞蹈性的感知上是否因流行度不同而显著不同?
-
检查我们前三大流派的流行度和舞蹈性的分布,分别用给定的x轴和y轴表示。
pythonsns.set_theme(style="ticks") g = sns.jointplot( data=df, x="popularity", y="danceability", hue="artist_top_genre", kind="kde", )你可以发现围绕一个整体汇聚点存在同心圆,显示出点的分布。
🎓 此示例使用 KDE(核密度估计)图表,使用连续概率密度曲线表示数据。这使我们能够解释多个分布的数据。
总体来说,三个流派在流行度和舞蹈性方面的大致趋势是相似的。要确定这些松散对齐的数据的聚类将是一项挑战:

-
绘制散点图:
pythonsns.FacetGrid(df, hue="artist_top_genre", height=5) \ .map(plt.scatter, "popularity", "danceability") \ .add_legend()使用相同坐标轴的散点图显示了相似的趋同模式

总的来说,对于聚类,你可以使用散点图来展示数据群集,掌握这种可视化方法非常有用。下一节课,我们将使用过滤后的数据并用 k-means 聚类方法发现数据中有趣重叠的群组。
🚀挑战
为下一节课做准备,制作一个关于各种聚类算法的图表,这些算法你可能会在生产环境中发现并使用。聚类试图解决什么样的问题?
课后测验
复习与自学
在应用聚类算法之前,正如我们所学,了解数据集的性质是个好主意。可在这里阅读更多相关内容。
这篇有用的文章带你了解在不同数据形状下各种聚类算法的不同表现方式。
作业
免责声明: 本文件由 AI 翻译服务 Co-op Translator 翻译完成。尽管我们力求准确,但请注意,自动翻译可能包含错误或不准确之处。原始语言版文件应视为权威来源。对于重要信息,建议使用专业人工翻译。我们对因使用本翻译而产生的任何误解或误释不承担责任。


