ML-For-Beginners 聚类章节深度指南:用无监督学习挖掘尼日利亚音乐口味模式
ML-For-Beginners 聚类章节深度指南用无监督学习挖掘尼日利亚音乐口味模式【免费下载链接】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 章节 为主体结合该章节下两节课程的完整代码与数据系统讲解聚类的核心概念、Scikit-learn 支持的聚类方法族、数据可视化探索流程以及 K-Means 聚类的完整实战含轮廓系数、肘部法则与方差问题。读完本文你将能对一份无标签数据集独立完成探索性可视化 → 特征选择 → K-Means 建模 → 质量评估 → 问题诊断的全流程并理解为什么真实数据聚类效果往往不理想、以及如何用特征缩放等手段改进。聚类是什么无监督学习的核心任务聚类是一类机器学习任务它自动寻找彼此相似的对象并将它们归入称为簇cluster的组。与机器学习中其他方法的最大区别在于一切都自动发生。事实上可以公平地说聚类是监督学习的反面——监督学习需要标签来训练模型而聚类不需要任何预定义输出。在 5-Clustering 章节 中教学主题围绕尼日利亚听众的音乐口味展开。尼日利亚的多元受众拥有多元的音乐偏好课程使用从 Spotify 采集的数据存储在 nigerian-songs.csv包含各歌曲的danceability舞蹈性、acousticness原声度、响度loudness、speechiness语言含量、popularity流行度和energy能量等信息目标是发现这些数据中的潜在模式。聚类特别适合数据集没有标签的场景如果数据有标签此前课程中学过的分类Classification技术通常更合适如果数据无标签聚类就是发现模式的最佳方式之一。值得说明的是聚类分析起源于 1930 年代的人类学与心理学领域至今已有近百年历史从洗袜子要按家庭成员分类的生活直觉到数据科学中分析用户偏好、刻画无标签数据集特征聚类的本质都是帮助我们从混乱中理出秩序。课程地图从可视化探索到 K-Means 建模本节课程由两节子课组成构成一条完整的学习路径聚类入门数据可视化 —— 用 Seaborn/Matplotlib 探索尼日利亚歌曲数据决定该用哪种聚类方法K-Means 聚类 —— 在过滤后的数据上训练 K-Means 模型学习轮廓系数Silhouette、肘部法则Elbow method、惯性Inertia与方差Variance四个关键概念。配套的作业用于巩固知识研究更多聚类可视化方式 和 尝试非 K-Means 的聚类方法。第一步认识 Scikit-learn 的聚类方法谱系在动手之前先建立全局视野。Scikit-learn 官方文档即 1-Visualize/README.md 所引用提供了一大批聚类方法选择哪种取决于你的具体用例。下表是课程整理的方法与其适用场景方法名适用场景K-Means通用目的归纳式inductiveAffinity propagation多簇、簇大小不均匀归纳式Mean-shift多簇、簇大小不均匀归纳式Spectral clustering少量、均匀的簇直推式transductiveWard hierarchical clustering多簇、带约束的簇直推式Agglomerative clustering多簇、带约束、非欧氏距离直推式DBSCAN非平面几何、不均匀簇直推式OPTICS非平面几何、密度可变的不均匀簇直推式Gaussian mixtures平面几何归纳式BIRCH含离群点的大数据集归纳式理解表中的关键术语直推式 vs. 归纳式Transductive vs. Inductive直推式推断由已观测的训练案例直接映射到特定测试案例归纳式推断则先从训练案例总结出通用规则再把这些规则应用于测试案例。课程给出一个生动的例子假设数据集部分已标注records、cds部分为空。归纳式方法会学习records和cds的特征并套用到未标注数据上但它难以处理真正的cassettes盒式磁带直推式方法则先把相似项聚成组再打标签簇可能反映圆形音乐物品与方形音乐物品这样的结构对未知数据更鲁棒。平面 vs. 非平面几何Flat vs. Non-flat geometry源于数学术语指测量点间距离的方式。平面指欧氏几何Euclidean距离按两点间线段的长度度量非平面指非欧氏几何距离沿曲线度量。如果你的数据可视化后明显不落在一个平面上就需要专门的算法来处理。距离Distances簇由它们的距离矩阵定义。欧氏簇以点值的平均定义包含一个质心centroid距离按到质心的距离度量非欧氏距离则指clustroid距离其他点最近的点clustroid 可以多种方式定义。约束聚类Constrained在这种无监督方法中引入半监督思想将点之间的关系标记为不能连接cannot-link或必须连接must-link从而对数据集施加规则。例如一个算法在无约束下可能把圆形音乐物品方形音乐物品三角形物品和饼干归成一组若加上物品必须由塑料制成物品必须能产生音乐这类约束就能引导算法做出更优的分组。密度Density数据嘈杂就被视为密集。各簇内点间距离可能稀疏或拥挤需要使用合适的聚类方法分析。例如用 K-Means 与 HDBSCAN 探索密度不均的嘈杂数据集效果差异明显。聚类算法的五大流派目前存在超过 100 种聚类算法选用哪种取决于手头数据的性质。课程重点讨论了以下主要类型层次聚类Hierarchical clustering如果一个对象根据其与邻近对象而非更远对象的接近程度被分类簇便基于成员相互之间的距离形成。Scikit-learn 的凝聚聚类agglomerative clustering即属此类。质心聚类Centroid clustering这种流行算法需要先选择k要形成的簇数然后算法确定簇的中心点并把数据聚集到该点周围。K-Means 是质心聚类最流行的版本——中心由最近的均值确定因此得名簇的平方距离被最小化。基于分布的聚类Distribution-based clustering基于统计建模核心是计算数据点属于某簇的概率并据此分配。高斯混合模型Gaussian mixture属于此类。基于密度的聚类Density-based clustering数据点依据密度彼此聚集程度被分配到簇中远离群体被视作离群点或噪声。DBSCAN、Mean-shift 和 OPTICS 属于此类。基于网格的聚类Grid-based clustering针对多维数据集创建网格并将数据划分到网格单元中从而形成簇。实战一用可视化探索尼日利亚歌曲数据聚类的效果高度依赖恰当的可视化因此第一步是可视化音乐数据。完整代码位于 1-Visualize/notebook.ipynb下面逐步展开。1. 安装依赖并加载数据!pip install seaborn import matplotlib.pyplot as plt import pandas as pd df pd.read_csv(5-Clustering/data/nigerian-songs.csv) df.head()注意课程 notebook 中数据路径写作../data/nigerian-songs.csv那是相对于 notebook 所在目录的写法从仓库根目录出发数据文件位于 5-Clustering/data/nigerian-songs.csv。实际运行时请按你的 notebook 位置调整路径。前几行数据展示了每首歌的完整字段歌名、专辑、艺人、艺人主打风格、发行年份、时长、流行度以及 8 个音频特征和节拍签名。2. 查看数据结构df.info()输出显示这是一个530 行、16 列的数据框列类型分布float648 列danceability、acousticness、energy、instrumentalness、liveness、loudness、speechiness、tempo、int644 列release_date、length、popularity、time_signature、object4 列name、album、artist、artist_top_genre所有列均为 530 个非空值内存占用约 66.4 KB。3. 检查缺失值与整体分布df.isnull().sum()16 列缺失值全部为 0数据完整。继续用df.describe()观察统计特征指标popularitydanceabilityenergytempomean17.510.7420.761116.49std18.990.1180.14923.52min00.2550.11161.70max730.9660.995206.01注意popularity存在大量 0 值——这意味着这些歌在数据集中没有排名随后需要剔除。另外课程在这里抛出一个值得思考的问题聚类是无监督方法、不需要标签为什么探索阶段还要展示带标签的数据答案是在数据探索阶段标签很方便但聚类算法本身并不需要它们——你完全可以去掉列头、用列号引用数据。4. 用条形图找出最流行的风格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)当排名第一的风格显示为 Missing 时表示 Spotify 未对其进行分类应将其剔除df df[df[artist_top_genre] ! Missing] top df[artist_top_genre].value_counts()重新绘制后可见afro dancehall、afropop、nigerian pop 三个风格主导了整个数据集。接下来聚焦这三类并过滤掉流行度为 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)]5. 相关性热力图判断特征间关联corrmat df.corr(numeric_onlyTrue) f, ax plt.subplots(figsize(12, 9)) sns.heatmap(corrmat, vmax.8, squareTrue)结论唯一的强相关出现在energy能量与loudness响度之间——响度大的音乐通常能量感强这一点并不令人意外除此之外各特征之间的相关性都相对较弱。这给聚类算法留下了悬念在这样的数据上聚类能发现什么注意相关不代表因果这里有相关性的证据但没有因果性的证据。6. 数据分布三种风格真的不同吗用jointplot绘制三种风格在流行度 × 舞蹈性上的核密度估计KDE分布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 diagram——包含一个点种子及其对应区域可参见 2-K-Means/images/voronoi.png 插图。K-Means 的三步迭代流程算法从数据集中采样选出 k 个中心点然后循环执行将每个样本分配给最近的质心取上一轮分配给各质心的所有样本的均值创建新质心计算新旧质心之间的差异重复直到质心稳定。K-Means 的一个缺点是你必须确定k质心数量。幸运的是**肘部法则elbow method**可以帮助估计 k 的良好初始值。完整代码位于 2-K-Means/notebook.ipynb它承接上一课的数据导入与初步清洗。1. 用箱线图观察离群点对每一列调用boxplot()12 个子图每个 3 列分布观察离群点plt.figure(figsize(20,20), dpi200) plt.subplot(4,3,1) sns.boxplot(x popularity, data df) # ... 依次对 acousticness、energy、instrumentalness、liveness、 # loudness、speechiness、tempo、time_signature、danceability、 # length、release_date 重复同样的调用数据有些嘈杂每个列都能看到离群点可参考 2-K-Means/images/boxplots.png。你可以逐一剔除这些离群点但那会让数据变得非常单薄。2. 选择特征并编码类别列挑选取值范围相近的列用于聚类并把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)这里X是 6 个特征构成的矩阵y是编码后的风格标签——虽然聚类不需要 y但它稍后用于评估模型与真实标签的一致程度。3. 训练第一个 K-Means 模型既然数据中只有 3 种风格先尝试 k3from 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输出一个数组为数据框每一行给出预测的簇编号0、1 或 2。4. 计算轮廓系数Silhouette scorefrom sklearn import metrics score metrics.silhouette_score(X, y_cluster_kmeans) score轮廓系数的取值在 -1 到 1 之间越接近 1表示簇越稠密且与其他簇分离良好接近 0 表示簇相互重叠样本非常接近相邻簇的决策边界。本例得分约为0.53正好处于中间——这说明当前数据并不特别适合这种聚类方式但课程决定继续往下走观察会发生什么。5. 用惯性构建肘部曲线接下来导入 KMeans循环 k1..10 计算各组内的 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聚类过程的迭代范围k 从 1 到 10random_state决定质心初始化的随机数生成设置固定值可保证结果可复现WCSSwithin-cluster sums of squares簇内平方和度量簇内所有点到簇质心的平方平均距离Inertia惯性K-Means 算法试图选择质心以最小化惯性即簇内部一致性的度量每次迭代把该值追加到wcss变量中k-meansScikit-learn 提供的初始化优化将质心初始化为通常彼此距离较远比随机初始化通常能得到更好的结果。6. 肘部法则确定最优 kplt.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确实等于 37. 展示聚类结果并评估准确率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)))这个模型的准确率并不理想而簇的形状给出了原因这份数据过于不平衡、相关性太弱、列值之间方差过大难以聚出良好形状。事实上形成的簇很可能被前面定义的三种风格类别严重主导或扭曲——这本身就是一次很有价值的学习过程方差问题与改进方向方差定义为与均值之差的平方的平均值。在这个聚类问题中它意味着数据集的数值偏离均值过多。Scikit-learn 文档展示了一类簇边界不清晰的模型正是典型的方差问题模型参见 2-K-Means/images/problems.png 插图。思考一下你能如何修正这个问题进一步调整数据例如剔除离群点换用不同的列换用不同的算法提示尝试对数据进行标准化scaling——notebook 中有被注释掉的代码添加标准缩放可以让各数据列在取值范围上更接近。你会发现在缩放后轮廓系数虽然下降但肘部曲线的拐点变平滑了。原因在于不缩放数据时方差较小的特征会携带更大权重例如取值范围 0~1 的 danceability 与范围可达 -19~0 的 loudness 相比后者在欧氏距离中的影响被放大。关于该问题的更多讨论可参见数据标准化对 K-Means 必要性的经典论述。课后挑战与延伸练习可视化挑战在准备下一课前制作一张关于各种聚类算法的图表思考在生产环境中可能会发现和使用哪些聚类算法这些聚类试图解决什么问题详见 1-Visualize/assignment.md优秀标准是提交包含 5 个文档完备散点图的 notebook。算法挑战K-Means 有时并不适合你的数据。请用本课或其他来源的数据展示一个不使用 K-Means的聚类方法并总结你学到了什么详见 2-K-Means/assignment.md。调参挑战花些时间在 notebook 中调整参数——更彻底地清洗数据如移除离群点、使用样本权重看看能否提升模型准确率创造更好的簇。小结本节课程从聚类 自动分组无标签数据这一核心思想出发先建立了 Scikit-learn 十大聚类方法的全局认知再通过尼日利亚 Spotify 歌曲数据完成了一次完整的实战闭环数据加载与清洗530 行、16 列、剔除 Missing 与流行度为 0 的记录→ 可视化探索柱状图、相关性热力图、KDE 联合分布、FacetGrid 散点图→ K-Means 建模特征选择、LabelEncoder、k3→ 质量评估轮廓系数 0.53、肘部法则→ 问题诊断方差过大、数据不平衡、特征间弱相关。最终结论很有启发并非所有数据都天然适合 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),仅供参考