尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

K-means聚类算法全解析:从原理推导到Python实战与调优

K-means聚类算法全解析:从原理推导到Python实战与调优 1. 项目概述从“一团乱麻”到“物以类聚”的实战利器刚接触数据建模或者数据分析的朋友经常会遇到一个头疼的问题手里有一大堆数据看起来杂乱无章怎么才能快速地把它们分门别类找出内在的规律比如电商平台有一百万用户怎么根据他们的购物行为分成几个有代表性的群体好进行精准营销又或者生物信息学里有一堆基因表达数据怎么把功能相似的基因归到一起这时候聚类模型就是你手里那把快刀而K-means算法无疑是这把刀里最锋利、最常用的一把。今天我就以一个过来人的身份带你彻底搞懂K-means从原理到每一步的数学计算再到手把手用Python实现让你不仅会用更明白为什么这么用避开我当年踩过的那些坑。简单说K-means要干的事就是给你一堆点数据让你把它们分成K个组。它的目标很“朴素”让同一个组里的点彼此尽量相似距离近不同组里的点尽量不同距离远。这个“距离”通常就是我们熟悉的欧几里得距离。整个算法就像一个不断优化的“分地盘”和“挪中心”的游戏直到地盘划分稳定为止。对于数学建模竞赛、数据分析项目或者机器学习入门来说掌握K-means是基本功因为它思想直观、实现简单、效果在多数场景下也足够可靠。接下来我们就深入这个算法的五脏六腑。2. K-means聚类算法核心原理全拆解2.1 算法思想与核心目标最小化“内讧”最大化“差异”K-means的核心思想可以用一个生活化的场景来理解假设你是班主任要把班上的学生按座位分成K个学习小组。你希望每个小组的成员坐得尽量近方便讨论同时不同小组之间离得尽量远避免互相干扰。一开始你随机指定了K个小组长初始中心点。然后你让每个学生选择离自己最近的小组长加入那个小组分配阶段。接着你发现小组形成后组长的位置可能不是组员的中心了于是你重新计算每个小组所有成员座位的平均位置并把小组长挪到那个新位置更新阶段。你不断重复“学生选组长”和“组长换位置”这两个步骤直到小组长的位置不再变化或者变化非常小分组就稳定了。用数学语言精确描述K-means的目标是最小化簇内平方和也就是最小化下面这个目标函数也叫畸变函数J Σ(i1 to k) Σ(x in C_i) ||x - μ_i||^2这里k是簇的个数C_i是第i个簇的集合μ_i是第i个簇的中心点质心||x - μ_i||就是数据点x到其所属簇中心μ_i的欧氏距离。这个J值越小说明同一个簇里的点越紧凑聚类效果就越好。整个算法的迭代过程就是在寻找能让J值达到局部最小的那种分组方式。注意这里说的是“局部最小”而不是“全局最小”。因为K-means的结果严重依赖于初始中心点的选择不同的起点可能会走向不同的终点局部最优解。这是K-means一个重要的特性也是我们需要在应用时特别注意的地方。2.2 算法步骤的魔鬼细节与数学推导理解了目标我们一步步拆解K-means的标准流程。我会把每一步背后容易被忽略的细节和数学计算都讲清楚。第一步初始化中心点Initialization这是整个算法的“起跑线”至关重要。通常我们会从数据集中随机选择K个点作为初始质心。但“随机”也有讲究。一种更优的方法是**K-means**初始化它的核心思想是让初始质心彼此尽量远离这样可以有效提高找到全局最优解的概率并减少迭代次数。其步骤是随机选择第一个质心。对于数据集中的每个点x计算它到已选质心的最短距离D(x)。按照D(x)^2的概率分布随机选择下一个质心距离越远的点被选中的概率越大。重复步骤2和3直到选出K个质心。第二步分配数据点到最近质心Assignment对于数据集中的每一个点x_i计算它到K个质心中每一个的距离通常是欧氏距离。然后将x_i分配给距离它最近的那个质心所在的簇。 数学上就是为每个点x_i找到簇标签c^(i)c^(i) arg min_j ||x^(i) - μ_j||^2这里arg min表示找到使后面表达式值最小的那个j质心编号。第三步重新计算质心Update所有点分配完毕后每个簇的成员就确定了。这时我们需要更新每个簇的质心。新的质心就是这个簇所有点的均值向量。 对于第j个簇其新质心μ_j的计算公式为μ_j (1 / |C_j|) * Σ(x in C_j) x其中|C_j|表示第j个簇中点的个数。简单说就是把这个簇里所有点的坐标在每个维度上分别求平均值。第四步迭代与收敛判断Iteration重复第二步分配和第三步更新直到满足停止条件。常见的停止条件有两种质心变化很小所有质心在新一轮迭代中的移动距离变化量都小于一个预设的阈值tol例如1e-4。即max(||μ_j_new - μ_j_old||) tol。目标函数变化很小前后两次迭代计算出的目标函数J值簇内平方和的减少量小于某个阈值。达到最大迭代次数为了防止无限循环通常会设置一个最大迭代次数max_iter比如300次。2.3 K-means的关键特性与内在局限没有完美的算法只有适合的场景。了解K-means的“脾气”和“短板”才能更好地驾驭它。对初始值敏感正如前面提到的随机初始化可能导致不同的局部最优解。解决方法就是多次运行比如10次选择目标函数J最小的那次结果作为最终输出。需要预先指定K值你必须告诉算法要分成几类。但在很多实际问题中K是未知的。这就需要借助“肘部法则”、“轮廓系数”等方法来辅助确定最佳的K值。对噪声和离群点敏感质心的计算是求均值离群点会显著地把质心“拉”向自己从而影响整个簇的分配。在数据预处理阶段处理好离群点很重要。适用于凸形簇K-means基于距离它隐含地假设簇是凸形的想象成一个球形或椭球形并且大小和密度相近。对于流形、环形等非凸形状的簇K-means的效果会很差。计算复杂度每次迭代需要计算所有点到所有质心的距离复杂度约为O(n * k * d * iter)其中n是样本数k是簇数d是维度iter是迭代次数。对于大规模数据可能需要优化或采用Mini-Batch K-means变种。3. 手把手Python实战从数据到聚类结果可视化理论说得再多不如一行代码。我们用一个完整的例子覆盖数据生成、模型训练、效果评估和可视化的全流程。我会使用scikit-learn和matplotlib这两个最主流的库。3.1 环境准备与数据生成首先确保你的Python环境安装了必要的库。如果没有在命令行执行pip install numpy scikit-learn matplotlib pandas。我们先用sklearn的make_blobs函数生成一份模拟数据。这样我们可以知道数据的真实分布ground truth便于评估聚类效果。import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_blobs from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score import warnings warnings.filterwarnings(ignore) # 忽略一些不影响运行的警告 # 1. 生成模拟数据 # n_samples: 样本总数 # centers: 真实的簇中心坐标这里我们设定为4个簇 # cluster_std: 每个簇的标准差控制簇的紧密程度 # random_state: 随机种子保证每次生成的数据相同便于复现 X, y_true make_blobs(n_samples500, centers4, cluster_std0.8, random_state42) # 2. 可视化原始数据 plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) plt.scatter(X[:, 0], X[:, 1], s30, cgray, alpha0.6, edgecolorsk) plt.title(Raw Data (Unlabeled)) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.grid(True, linestyle--, alpha0.5)这段代码生成了500个样本点它们实际上来自4个不同的“ blob ”团状分布。y_true存储了每个样本真实的类别标签0,1,2,3但在聚类任务中我们假装不知道这个信息。右图展示了数据的原始分布。3.2 模型训练、预测与基础可视化接下来我们使用K-means进行聚类并将结果与真实分布对比。# 3. 创建KMeans模型并拟合数据 # n_clusters: 这是我们猜测的簇数这里我们“猜”对了是4 # initk-means: 使用K-means初始化优于纯随机 # n_init10: 用不同的初始质心运行10次算法会自动选择结果最好J最小的一次 # max_iter300: 最大迭代次数 # random_state42: 固定随机种子保证结果可复现 kmeans KMeans(n_clusters4, initk-means, n_init10, max_iter300, random_state42) y_pred kmeans.fit_predict(X) # fit_predict一步完成训练和预测 # 获取聚类中心 centroids kmeans.cluster_centers_ # 4. 可视化聚类结果 plt.subplot(1, 2, 2) # 用预测的标签作为颜色 scatter plt.scatter(X[:, 0], X[:, 1], s30, cy_pred, cmapviridis, alpha0.8, edgecolorsk) # 画出质心 plt.scatter(centroids[:, 0], centroids[:, 1], s250, marker*, cred, edgecolorsblack, linewidth1.5, labelCentroids) plt.title(K-means Clustering Result (K4)) plt.xlabel(Feature 1) plt.ylabel(Feature 2) plt.legend() plt.grid(True, linestyle--, alpha0.5) plt.colorbar(scatter, labelCluster Label) plt.tight_layout() plt.show() # 打印一些关键信息 print(f迭代次数: {kmeans.n_iter_}) print(f簇内平方和Inertia: {kmeans.inertia_:.2f}) print(f质心坐标:\n{centroids})运行后你会看到右图的数据点被分成了四种颜色并且用红色星号标出了四个质心。inertia_属性就是我们的目标函数J即簇内平方和。对比左右两图如果聚类成功右图的颜色块应该大致对应左图中自然的“一团一团”的数据。3.3 如何确定最佳的K值——肘部法则与轮廓系数在实际项目中我们不知道K是多少。这时候就需要技术手段来辅助判断。最常用的两种方法是肘部法则和轮廓系数。肘部法则其原理是随着K增大簇内平方和inertia会下降。当K小于真实簇数时增加K会大幅降低inertia当K达到真实簇数后再增加Kinertia的下降幅度会突然变缓。这个拐点就像“手肘”对应的K就是建议值。# 肘部法则 inertias [] K_range range(1, 11) # 测试K从1到10 for k in K_range: kmeans KMeans(n_clustersk, random_state42) kmeans.fit(X) inertias.append(kmeans.inertia_) plt.figure(figsize(10, 4)) plt.subplot(1, 2, 1) plt.plot(K_range, inertias, bo-) plt.xlabel(Number of clusters (K)) plt.ylabel(Inertia (Within-cluster Sum of Squares)) plt.title(The Elbow Method) plt.grid(True)轮廓系数它结合了簇内的凝聚度和簇间的分离度。对于每个样本点ia(i):i到同簇其他点的平均距离凝聚度。b(i):i到其他某个簇所有点的平均距离的最小值分离度。轮廓系数s(i) (b(i) - a(i)) / max(a(i), b(i))s(i)的取值范围在[-1, 1]之间。值越接近1说明该样本聚类越合理越接近-1说明可能被分错了簇接近0则说明样本在两个簇的边界上。所有样本的s(i)的均值称为平均轮廓系数。# 轮廓系数 silhouette_scores [] for k in K_range[1:]: # 轮廓系数要求K2 kmeans KMeans(n_clustersk, random_state42) y_pred kmeans.fit_predict(X) score silhouette_score(X, y_pred) silhouette_scores.append(score) plt.subplot(1, 2, 2) plt.plot(list(K_range)[1:], silhouette_scores, go-) plt.xlabel(Number of clusters (K)) plt.ylabel(Silhouette Score) plt.title(Silhouette Analysis) plt.grid(True) plt.tight_layout() plt.show() # 找出轮廓系数最大的K best_k_sil list(K_range)[1:][np.argmax(silhouette_scores)] print(f根据轮廓系数建议的K值为: {best_k_sil})将两个图放在一起看。在肘部法则图中我们寻找“肘点”即曲线斜率明显变化的点上图中可能在K3或4处。在轮廓系数图中我们寻找峰值点。结合两者K4是一个强有力的候选。这和我们生成数据时设定的centers4是一致的。3.4 高级可视化决策边界与聚类过程动画思路为了更直观地理解K-means如何划分“地盘”我们可以绘制其决策边界Voronoi图。决策边界就是平面上的这样一些线线上的点到两个不同质心的距离相等。# 绘制决策边界 def plot_decision_boundaries(X, model, ax): # 创建网格点 h 0.02 # 网格步长 x_min, x_max X[:, 0].min() - 1, X[:, 0].max() 1 y_min, y_max X[:, 1].min() - 1, X[:, 1].max() 1 xx, yy np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) # 预测网格上每个点的标签 Z model.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘制决策区域 ax.contourf(xx, yy, Z, alpha0.3, cmapviridis) # 绘制数据点 ax.scatter(X[:, 0], X[:, 1], cmodel.labels_, s30, edgecolorsk, cmapviridis) # 绘制质心 ax.scatter(model.cluster_centers_[:, 0], model.cluster_centers_[:, 1], s250, marker*, cred, edgecolorsblack, labelCentroids) ax.set_title(fK-means Decision Boundaries (K{model.n_clusters})) ax.legend() ax.grid(True, linestyle--, alpha0.5) fig, ax plt.subplots(figsize(8, 6)) plot_decision_boundaries(X, kmeans, ax) plt.show()这张图清晰地展示了K-means基于距离的线性划分特性每个多边形区域泰森多边形内的点都离本区域的红色星号质心最近。至于聚类过程动画其核心思路是在每次迭代后即更新质心后保存当前的数据点分配情况和质心位置然后用matplotlib.animation模块将这些静态帧串联成动画。这能非常生动地展示“分配”和“更新”两个步骤如何交替进行直至收敛。由于代码较长这里给出关键步骤自定义一个KMeans类在其fit方法中记录每一轮迭代的中间状态labels_history,centers_history。使用FuncAnimation函数定义一个更新函数在每一帧绘制对应的数据和质心。将动画保存为GIF或直接显示。4. 实战进阶处理非球形数据与特征缩放4.1 K-means的“阿喀琉斯之踵”非凸簇我们之前生成的数据是“一团一团”的球形数据这是K-means的主场。现在我们来看一个经典的、K-means会失效的例子同心圆或月牙形数据。我们用make_circles生成数据。from sklearn.datasets import make_circles, make_moons # 生成同心圆数据 X_circles, y_circles make_circles(n_samples500, factor0.5, noise0.05, random_state42) # 生成月牙形数据 X_moons, y_moons make_moons(n_samples500, noise0.08, random_state42) fig, axes plt.subplots(1, 2, figsize(12, 5)) # 绘制原始数据 axes[0].scatter(X_circles[:, 0], X_circles[:, 1], cy_circles, s30, cmapbwr, edgecolorsk) axes[0].set_title(Two Circles (Ground Truth)) axes[0].grid(True, linestyle--, alpha0.5) axes[1].scatter(X_moons[:, 0], X_moons[:, 1], cy_moons, s30, cmapcoolwarm, edgecolorsk) axes[1].set_title(Two Moons (Ground Truth)) axes[1].grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.show()现在我们用K2的K-means去聚类这两个数据集。# 对同心圆数据应用K-means kmeans_circles KMeans(n_clusters2, random_state42) y_pred_circles kmeans_circles.fit_predict(X_circles) # 对月牙形数据应用K-means kmeans_moons KMeans(n_clusters2, random_state42) y_pred_moons kmeans_moons.fit_predict(X_moons) fig, axes plt.subplots(1, 2, figsize(12, 5)) axes[0].scatter(X_circles[:, 0], X_circles[:, 1], cy_pred_circles, s30, cmapbwr, edgecolorsk) axes[0].scatter(kmeans_circles.cluster_centers_[:, 0], kmeans_circles.cluster_centers_[:, 1], s250, marker*, cyellow, edgecolorsblack) axes[0].set_title(K-means on Circles (Fails)) axes[0].grid(True, linestyle--, alpha0.5) axes[1].scatter(X_moons[:, 0], X_moons[:, 1], cy_pred_moons, s30, cmapcoolwarm, edgecolorsk) axes[1].scatter(kmeans_moons.cluster_centers_[:, 0], kmeans_moons.cluster_centers_[:, 1], s250, marker*, cyellow, edgecolorsblack) axes[1].set_title(K-means on Moons (Fails)) axes[1].grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.show()你会发现K-means完全失败了。对于同心圆它根据到两个质心的直线距离把数据切成了两个半圆而不是内外两个环。对于月牙形结果同样错误。这是因为K-means的“距离”假设欧氏距离和“质心”概念均值天然地倾向于寻找球状的簇。这是K-means最根本的局限性之一。对于这类数据应该考虑使用**谱聚类Spectral Clustering或DBSCANDensity-Based Spatial Clustering of Applications with Noise**等基于密度或图的聚类算法。它们能发现任意形状的簇。4.2 特征缩放为什么以及如何做K-means基于距离因此它受特征量纲的影响非常大。假设你的数据有两个特征一个是“年薪”单位万元范围0-100另一个是“年龄”单位岁范围20-60。如果不做处理计算距离时“年薪”的微小波动比如1万元对距离的贡献会远远小于“年龄”的波动1岁。这会导致聚类结果完全由“年薪”主导“年龄”特征几乎不起作用。解决方案是进行特征标准化。最常用的两种方法是Z-score标准化Standardization:x_new (x - mean) / std。将数据缩放为均值为0标准差为1的分布。这是最推荐用于K-means的方法。Min-Max归一化Normalization:x_new (x - min) / (max - min)。将数据缩放到[0, 1]区间。我们用sklearn的StandardScaler来演示其重要性。from sklearn.preprocessing import StandardScaler # 假设我们有一份包含不同量纲特征的数据 # 特征1: 收入千元范围 [20, 150] # 特征2: 年龄岁范围 [20, 60] np.random.seed(42) income np.random.randint(20, 150, 100) age np.random.randint(20, 60, 100) X_original np.column_stack((income, age)) # 不进行缩放 kmeans_raw KMeans(n_clusters3, random_state42).fit(X_original) inertia_raw kmeans_raw.inertia_ # 进行Z-score标准化 scaler StandardScaler() X_scaled scaler.fit_transform(X_original) kmeans_scaled KMeans(n_clusters3, random_state42).fit(X_scaled) inertia_scaled kmeans_scaled.inertia_ print(f原始数据簇内平方和: {inertia_raw:.2f}) print(f标准化后簇内平方和: {inertia_scaled:.2f}) # 可视化对比 fig, axes plt.subplots(1, 2, figsize(12, 5)) axes[0].scatter(X_original[:, 0], X_original[:, 1], ckmeans_raw.labels_, cmaptab10, s30) axes[0].scatter(kmeans_raw.cluster_centers_[:, 0], kmeans_raw.cluster_centers_[:, 1], s200, markers, cred, edgecolorsblack) axes[0].set_xlabel(Income (k)) axes[0].set_ylabel(Age) axes[0].set_title(Clustering on Raw Data) axes[0].grid(True, linestyle--, alpha0.5) axes[1].scatter(X_scaled[:, 0], X_scaled[:, 1], ckmeans_scaled.labels_, cmaptab10, s30) axes[1].scatter(kmeans_scaled.cluster_centers_[:, 0], kmeans_scaled.cluster_centers_[:, 1], s200, markers, cred, edgecolorsblack) axes[1].set_xlabel(Income (Standardized)) axes[1].set_ylabel(Age (Standardized)) axes[1].set_title(Clustering on Scaled Data) axes[1].grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.show()你会发现两幅图的聚类结果截然不同。在原始数据图中由于收入值远大于年龄值聚类边界几乎是垂直的这意味着聚类几乎只由收入决定。而在标准化后的图中两个特征被赋予了同等的重要性聚类边界是倾斜的综合考虑了收入和年龄。因此在运行K-means之前对数据进行标准化是必不可少的一步。5. 常见问题、调优技巧与项目实战心得5.1 高频问题排查指南在实际使用中你肯定会遇到各种问题。下面这个表格整理了一些典型情况及其解决思路。问题现象可能原因排查与解决思路聚类结果不稳定每次运行结果都不一样1. 初始质心随机选择导致陷入不同局部最优。2. 数据中存在大量噪声或离群点。1. 使用n_init参数如设为10或50让算法多次运行并选择最佳结果。2. 使用initk-means初始化策略。3. 预处理数据处理或剔除离群点。“肘部”不明显无法确定K值1. 数据本身没有明显的簇结构可能是均匀分布。2. 数据维度太高或特征间相关性太强。1. 结合轮廓系数、Calinski-Harabasz指数等多种指标综合判断。2. 考虑先用PCA等降维方法观察数据或直接尝试基于密度的聚类算法如DBSCAN。3. 从业务角度理解确定一个合理的K值范围。轮廓系数普遍很低接近0或为负1. 选择的K值不合适。2. 数据不适合用K-means聚类如非凸形状。3. 特征未标准化距离计算失真。1. 尝试不同的K值观察轮廓系数的变化。2. 可视化数据分布检查是否为球形簇。若不是换用谱聚类、DBSCAN等。3.务必检查并执行特征标准化。某个簇非常大其他簇非常小1. 数据分布极度不均衡。2. K值设置过大算法强行分割了本应属于一个的大簇。1. 检查数据看是否本身就是不均衡的。如果是业务事实则结果合理。2. 尝试减小K值或使用能处理大小不一簇的算法。3. 考虑对样本进行加权或采用分层抽样后再聚类。算法收敛很慢迭代次数达到max_iter1. 数据量太大或维度太高。2. 初始质心选择太差。3. 收敛阈值tol设置过小。1. 对于大数据集使用MiniBatchKMeans。2. 确保使用initk-means。3. 适当增大tol如从1e-4调到1e-3或适当减小max_iter。质心坐标出现NaN非数字某个簇在迭代过程中失去了所有样本点成为空簇。1. 检查初始质心是否合理避免初始点离所有数据都太远。2. 使用更鲁棒的初始化方法k-means。3. 在自定义实现K-means时需要加入处理空簇的逻辑如将一个质心重置为一个随机数据点。5.2 参数调优与高级技巧除了基本的n_clusters,init,n_init,max_iter,tol还有一些进阶技巧可以提升模型表现。algorithm参数sklearn的KMeans提供了三种算法“lloyd”经典EM迭代、“elkan”利用三角不等式减少距离计算对稠密数据更快和“auto”自动选择。对于稀疏数据“lloyd”是唯一选择。通常用默认的“auto”即可。处理空簇在自定义实现或某些极端情况下可能出现空簇。一个简单的策略是将空簇的质心设置为离当前最大簇的质心最远的一个数据点或者直接设置为一个随机数据点。结合PCA降维当特征维度很高10时高维空间中的距离计算会变得不稳定且难以解释“维度灾难”。可以先使用主成分分析PCA将数据降到2-3维可视化观察其大致结构并在此低维空间进行聚类。这不仅能加速计算有时还能得到更鲁棒的结果。MiniBatchKMeans对于海量数据如百万级以上标准的K-means会非常慢。MiniBatchKMeans每次迭代只使用数据的一个随机子集mini-batch来更新质心极大地减少了计算量通常能以轻微的性能损失换取巨大的速度提升。from sklearn.cluster import MiniBatchKMeans # 假设X_large是一个非常大的数据集 # mbk MiniBatchKMeans(n_clusters5, batch_size1024, random_state42).fit(X_large)5.3 项目实战心得与避坑指南结合我多次在数模竞赛和实际项目中使用K-means的经验分享几点最重要的心得第一可视化先行永远不要相信黑箱。在确定K值、评估效果前尽可能地将数据可视化。即使是高维数据也可以用PCA或t-SNE降到2D/3D来观察。如果肉眼都看不出明显的“一团一团”那K-means很可能不是最佳选择。对于非球形数据可视化能立刻让你意识到问题。第二数据预处理的质量决定天花板。K-means对数据质量非常敏感。除了必须做的特征标准化还要重点关注缺失值处理K-means不能直接处理缺失值。需要根据情况用均值、中位数填充或直接删除缺失样本。离群点处理离群点会像磁铁一样把质心“吸”过去。可以使用Z-score方法如将|Z|3的点视为离群点或IQR方法识别并处理。特征工程有时直接使用原始特征效果不好。考虑创建更有意义的衍生特征或者使用领域知识进行特征选择剔除不相关或冗余的特征。第三K值的确定是艺术与科学的结合。肘部法则和轮廓系数是科学工具但最终的K值一定要结合业务逻辑来判断。比如做客户分群分5群还是8群不仅要看指标还要看分出来的每个群体是否有清晰的业务画像和可操作的营销策略。一个无法解释和落地的聚类结果是没用的。第四理解“没有银弹”做好算法选型。K-means简单高效是很好的基线模型和探索工具。但它不是万能的。如果数据是密度不均的、流形的、包含噪声的要果断考虑DBSCAN、谱聚类、层次聚类等其他算法。在实际项目中我常常会先用K-means快速跑一个基线再用更复杂的算法去对比提升。第五聚类结果的评估与解释。聚类是无监督学习没有绝对正确的标签。除了轮廓系数、Calinski-Harabasz指数等内部评估指标更重要的是外部评估和业务解释。你需要回答每个簇有什么特征计算每个簇在各个特征上的均值/分布这些簇在业务上代表什么如“高价值活跃用户”、“低频价格敏感用户”只有能讲出故事的聚类才是有价值的聚类。
返回列表