五华区网站,为校园网站建设提供,wordpress 文件说明,传奇端游平台从零开始掌握聚类分析#xff1a;探索数据背后的隐藏模式与应用实例 基本概念聚类分类聚类算法的评价指标#xff08;1#xff09;内部指标轮廓系数#xff08;Silhouette Coefficient#xff09;DB指数#xff08;Davies-Bouldin Index#xff09;Dunn指数 #xff08… 从零开始掌握聚类分析探索数据背后的隐藏模式与应用实例 基本概念聚类分类聚类算法的评价指标1内部指标轮廓系数Silhouette CoefficientDB指数Davies-Bouldin IndexDunn指数 2外部指标Jaccard系数Fowlkes-Mallows指数FMI兰德指数Rand Index 常见聚类算法简介基于划分的聚类算法——K-Means算法数学表示算法步骤1. 初始化2. 分配步骤3. 更新步骤4. 迭代 收敛性缺点与限制 基于密度的聚类算法——DBSCAN算法数学表示与关键概念关键概念 算法步骤1. 初始化2. 扩展簇3. 标记非核心点4. 处理噪声 数学公式收敛性与复杂度缺点与限制实际应用中的考虑 基于层次的聚类算法——AGNES 算法数学表示与关键概念初始设置距离度量与相似性度量 算法步骤1. 初始化2. 计算距离矩阵3. 合并最近的簇4. 重复合并5. 结果解释 收敛性与复杂度缺点与限制实际应用中的考虑 基于网格的聚类算法——STINGStatistical Information Grid和 CLIQUEClustering In QUEst基于网格的聚类算法概述STING 算法概念与原理数学公式与关键概念算法步骤 CLIQUE 算法概念与原理数学公式与关键概念算法步骤 收敛性与复杂度缺点与限制 基于模型的聚类算法——高斯混合模型Gaussian Mixture Model, GMM数学表示与关键概念模型定义参数估计 EM 算法步骤1. 初始化2. E 步期望步3. M 步最大化步4. 迭代 收敛性与复杂度缺点与限制总结 聚类算法实战——K-Means算法——购物中心客户分群分析业务背景仿真数据说明聚类目标商业价值使用K-Means解决问题完整代码——K-Means完整代码——DBSCAN 聚类算法实战——DBSCAN算法——城市公共自行车站点分布分析业务背景数据说明分析目标分析价值使用DBSCAN解决问题完整代码 总结 基本概念
聚类Clustering 是一种无监督学习方法其目的是将一组数据点分成若干个簇clusters使得同一簇内的数据点彼此之间具有较高的相似性而不同簇之间的数据点相似性较低。然而一共有几个蔟不是事先给定的是由待分类的数据的特征决定的。简单来说聚类的目的就是通过无监督学习的方法发现数据中的自然分组结构将数据分为几堆这样
那什么是簇呢簇是一组具有相似特征的数据点或对象组成的集合。简单来说簇是数据点按照某种相似性度量被分组的结果其中每个簇内的成员彼此之间比与其他簇的成员更加相似。就像在一个菜篮子里面通过辨识篮子里面蔬菜的特征将蔬菜分成了几类、几堆。
聚类分类
根据不同的聚类原理和算法特点聚类算法可以分为以下几类
基于划分的聚类算法如K-Means、K-Medoids、CLARANS等。这类算法通过迭代优化目标函数将数据集划分为预定的K个簇。基于密度的聚类算法如DBSCAN、OPTICS、Mean Shift等。这类算法通过密度可达性来识别簇能够识别出任意形状的簇。基于层次的聚类算法如AGNES自底向上、DIANA自顶向下等。这类算法通过逐步合并或分裂现有的簇形成一棵聚类树。基于网格的聚类算法如STING、WaveCluster等。这类算法将数据空间划分为有限数量的单元格形成网格结构然后在网格上进行聚类。基于模型的聚类算法如高斯混合模型GMM、隐马尔可夫模型HMM等。这类算法假设数据由一系列的概率分布生成通过优化模型参数来进行聚类。
聚类算法的评价指标
聚类算法的评价指标又称为性能度量指标透过这个指标我们可以分析聚类算法的聚类结果的好坏。通常认为通过聚类算法之后簇内相似度越高算法分类效果越好蔟间相似度越低算法分类效果越好反之。
聚类算法的评价通常依赖于内部指标和外部指标两大类。下面一一讲解着两种指标
1内部指标
内部指标主要衡量聚类结果的紧凑性和分离性不需要外部参考模型或基准数据它是直接通过考察聚类结果得出的。常见的内部指标包括
轮廓系数Silhouette Coefficient
轮廓系数是衡量聚类效果的一个综合指标它结合了簇内凝聚度和簇间分离度。对于每个样本点轮廓系数定义为 s ( i ) b ( i ) − a ( i ) max { a ( i ) , b ( i ) } s(i) \frac{b(i) - a(i)}{\max\{a(i), b(i)\}} s(i)max{a(i),b(i)}b(i)−a(i) 其中 a ( i ) a(i) a(i) 是样本点 i i i 到同一簇内其他点的平均距离衡量了簇内的凝聚度。 b ( i ) b(i) b(i) 是样本点 i i i 到最近的其他簇中点的平均距离衡量了簇间的分离度。
轮廓系数的取值范围为 [ − 1 , 1 ] [-1, 1] [−1,1]其中 s ( i ) s(i) s(i) 接近 1 表示样本点 i i i 被很好地分配到了正确的簇中、接近 0 表示样本点 i i i 可能处于两个簇的边界上、接近 -1 表示样本点 i i i 被分配到了错误的簇中。
对于整个数据集轮廓系数是所有样本点的轮廓系数的平均值。
DB指数Davies-Bouldin Index
DB指数是衡量聚类效果的一个指标它基于簇内紧凑度和簇间分离度的比值。DB指数的公式为 D B 1 k ∑ i 1 k max j ≠ i ( σ i σ j d ( c i , c j ) ) DB \frac{1}{k} \sum_{i1}^{k} \max_{j \neq i} \left( \frac{\sigma_i \sigma_j}{d(c_i, c_j)} \right) DBk1i1∑kjimax(d(ci,cj)σiσj) 其中 k k k 是簇的数量。 σ i \sigma_i σi 和 σ j \sigma_j σj 分别是簇 i i i 和簇 j j j 的平均簇内距离。 d ( c i , c j ) d(c_i, c_j) d(ci,cj) 是簇 i i i 和簇 j j j 的中心点之间的距离。 max j ≠ i \max_{j \neq i} maxji 表示对所有的 j j j 不等于 i i i 的簇进行计算。
DB指数的值越小表示聚类效果越好因为这意味着簇内距离较小而簇间距离较大。
Dunn指数
Dunn指数是基于簇间最小距离和簇内最大距离的一个比值用于衡量聚类的紧密度和分离度。Dunn指数的公式为 D I min 1 ≤ i ≤ k { min j ≠ i ( d min ( C i , C j ) max 1 ≤ l ≤ k d max ( C l ) ) } DI \min_{1 \leq i \leq k} \left\{ \min_{j \neq i} \left( \frac{d_{\min}(C_i, C_j)}{\max_{1 \leq l \leq k} d_{\max}(C_l)} \right) \right\} DI1≤i≤kmin{jimin(max1≤l≤kdmax(Cl)dmin(Ci,Cj))} 其中 d min ( C i , C j ) d_{\min}(C_i, C_j) dmin(Ci,Cj) 是簇 C i C_i Ci 和簇 $ C_j$ 之间的最小距离。 d max ( C l ) d_{\max}(C_l) dmax(Cl) 是簇 C l C_l Cl 内的最大距离。 min 1 ≤ i ≤ k \min_{1 \leq i \leq k} min1≤i≤k 和 min j ≠ i \min_{j \neq i} minji 分别表示对所有的簇进行最小值计算。
Dunn指数的值越大表示聚类效果越好因为簇间的最小距离相对较小而簇内的最大距离相对较大说明簇之间分离得较好簇内数据点较为紧密。
2外部指标
外部指标需要借助外部某个参考模型或已知数据集的真实标签来评估聚类结果的准确性。常见的外部指标包括
Jaccard系数
Jaccard系数是衡量两个集合相似度的一个指标它通过比较两个集合的交集和并集的大小来确定它们的相似程度。在聚类分析中Jaccard系数可以用来衡量两个簇之间的相似度。数学公式如下 J ( A , B ) ∣ A ∩ B ∣ ∣ A ∪ B ∣ J(A, B) \frac{|A \cap B|}{|A \cup B|} J(A,B)∣A∪B∣∣A∩B∣
其中 ∣ A ∩ B ∣ |A \cap B| ∣A∩B∣ 是簇 A 和簇 B 的交集的元素数量。 ∣ A ∪ B ∣ |A \cup B| ∣A∪B∣ 是簇 A 和簇 B 的并集的元素数量。
Jaccard系数的取值范围是 [0, 1]其中 0 表示两个簇没有交集1 表示两个簇完全相同。值越大表示两个簇越相似。
Fowlkes-Mallows指数FMI
Fowlkes-Mallows指数是基于簇对的正确匹配和错误匹配来评估聚类效果的指标。它通过计算正确匹配的元素对数量的平方与所有匹配对正确匹配和错误匹配的总数之比来衡量聚类的质量。数学公式如下 F M I T P 2 T P F P F N FMI \frac{TP^2}{TP FP FN} FMITPFPFNTP2
其中 T P TP TP 是正确匹配的元素对数量即两个簇中都有相同标签的元素对。 F P FP FP 是错误匹配的元素对数量即两个簇中标签不同的元素对。 F N FN FN 是未匹配的元素对数量即至少有一个簇中没有标签的元素对。
FMI的取值范围是 [0, 1]值越大表示聚类效果越好。
兰德指数Rand Index
兰德指数是衡量聚类结果与真实标签一致性的指标。它通过计算正确匹配的元素对数量与所有可能元素对的数量之比来评估聚类的准确性。数学公式如下 R I T P T N T P T N F P F N RI \frac{TP TN}{TP TN FP FN} RITPTNFPFNTPTN
其中 T P TP TP 是正确匹配的元素对数量。 T N TN TN 是两个簇中都没有相同标签的元素对数量。 F P FP FP 是错误匹配的元素对数量。 F N FN FN 是未匹配的元素对数量。
RI的取值范围也是 [0, 1]值越大表示聚类结果与真实标签的一致性越高。 请注意这些指标的计算通常需要真实的聚类标签因此在实际应用中它们主要用于评估聚类算法的性能特别是在有监督学习环境中。在没有真实标签的情况下这些指标无法直接应用。
常见聚类算法简介
基于划分的聚类算法——K-Means算法
K-Means算法是一种经典的基于划分的聚类算法特别适用于大规模数据集。其基本思想是给定一个数据集和一个整数K算法通过迭代过程将数据集划分为K个簇使得每个数据点与其所属簇的中心点均值的距离之和最小最终形成若干个圆形或椭圆形的簇。
数学表示
设我们有 n n n个数据点 { x 1 , x 2 , . . . , x n } \{x_1,x_2,...,x_n\} {x1,x2,...,xn}其中每个 x i ∈ R d x_i\in\mathbb{R}^d xi∈Rd表示一个 d d d维向量。我们的目标是找到 k k k个簇心 { μ 1 , μ 2 , . . . , μ k } \{\mu_1,\mu_2,...,\mu_k\} {μ1,μ2,...,μk}使得所有点到它们所属簇心的距离平方和最小化 J ∑ i 1 k ∑ x j ∈ C i ∣ ∣ x j − μ i ∣ ∣ 2 J\sum_{i1}^{k}\sum_{x_j\in C_i}||x_j-\mu_i||^2 Ji1∑kxj∈Ci∑∣∣xj−μi∣∣2
这里 C i C_i Ci表示第 i i i个簇中的所有点 μ i \mu_i μi是第 i i i个簇的簇心而 ∣ ∣ x j − μ i ∣ ∣ 2 ||x_j-\mu_i||^2 ∣∣xj−μi∣∣2是欧几里得距离的平方。
算法步骤
K-Means 算法由两个主要步骤组成分配Assignment和更新Update。这两个步骤交替进行直到收敛。
1. 初始化
选择初始簇心随机选择 k k k个数据点作为初始簇心或者使用更复杂的初始化方法如K-Means来提高效率。
2. 分配步骤
对于每个数据点 x j x_j xj计算它与所有簇心之间的距离并将其分配给最近的那个簇心所在的簇。具体来说对于每一个数据点 x j x_j xj我们找到使下式最小化的 i i i i arg min i ′ ∣ ∣ x j − μ i ′ ∣ ∣ 2 i\arg\min_{i}||x_j-\mu_{i}||^2 iargi′min∣∣xj−μi′∣∣2
这一步骤可以写作 C i { x j : ∣ ∣ x j − μ i ∣ ∣ 2 ≤ ∣ ∣ x j − μ i ′ ∣ ∣ 2 , ∀ i ′ ≠ i } C_i\{x_j:||x_j-\mu_i||^2\leq||x_j-\mu_{i}||^2,\forall i\neq i\} Ci{xj:∣∣xj−μi∣∣2≤∣∣xj−μi′∣∣2,∀i′i}
3. 更新步骤
一旦所有点都被分配给了某个簇接下来需要重新计算每个簇的新簇心。新簇心是该簇中所有点的平均值 μ i 1 ∣ C i ∣ ∑ x j ∈ C i x j \mu_i\frac{1}{|C_i|}\sum_{x_j\in C_i}x_j μi∣Ci∣1xj∈Ci∑xj
这里 ∣ C i ∣ |C_i| ∣Ci∣表示簇 C i C_i Ci中的数据点数量。
4. 迭代
重复执行分配和更新步骤直到满足以下任一条件
簇心不再显著变化即在两次连续迭代之间簇心位置的变化非常小。达到了预设的最大迭代次数。
收敛性
K-Means 算法保证每次迭代都会减少目标函数 J J J因此它会逐渐收敛到局部最优解。然而由于K-Means使用梯度下降的一种变体它可能陷入局部最优而非全局最优。为了减轻这个问题通常会多次运行算法每次使用不同的初始簇心并选择产生最低 J J J值的结果。
缺点与限制
尽管K-Means算法简单且高效但它也有一些局限性
它假设簇为球形分布这对于非球形簇效果不佳。对异常值敏感因为这些点可能会对簇心的位置产生较大影响。需要事先指定 k k k的值选择不当可能导致不理想的聚类结果。只能处理数值型数据无法直接应用于分类或文本数据。
希望这个详细的介绍能够帮助你更好地理解K-Means算法的工作机制及其背后的数学原理。如果你有任何疑问或者想要了解更多信息请随时提问
基于密度的聚类算法——DBSCAN算法
DBSCANDensity-Based Spatial Clustering of Applications with Noise是一种基于密度的聚类算法能够识别任意形状的簇并且对噪声点具有鲁棒性。与 K-Means 不同DBSCAN 不需要预先指定簇的数量而是根据数据点的密度自动确定簇的数量和形状。它特别适用于发现自然存在的簇结构并能有效处理噪声数据。
数学表示与关键概念
DBSCAN 的核心思想是通过定义两个参数来确定哪些点属于同一个簇 E p s Eps Eps邻域半径距离用来定义邻域范围。 M i n P t s MinPts MinPts最小点数定义一个点成为核心点所需的最少邻居数量包括自身。
关键概念
核心点Core Point如果一个点在其 E p s Eps Eps 范围内至少包含 M i n P t s MinPts MinPts 个点则该点为核心点。边界点Border Point不是核心点但在某个核心点的 E p s Eps Eps 范围内的点。噪声点Noise Point既不是核心点也不是边界点的数据点。
这些概念决定了点之间的可达性和连通性从而影响簇的形成。
算法步骤
DBSCAN 算法通过以下详细步骤构建簇
1. 初始化
选择一个未访问的数据点作为起点。检查该点是否为核心点。如果是则创建一个新的簇如果不是则标记为噪声点。
2. 扩展簇
对于每个找到的核心点从它的邻域开始扩展新的簇。具体过程如下
对于当前点 p p p如果它是核心点则创建一个新的簇 C C C并将所有在 p p p 的 E p s Eps Eps 范围内的点添加到 C C C 中。对于新加入簇的每个点 q q q如果 q q q 也是核心点则将 q q q 的所有未访问邻居也加入到 C C C 中并继续这个过程直到不再有新的点可以加入。
3. 标记非核心点
对于不是核心点但位于某个核心点的 E p s Eps Eps 范围内的点标记为边界点并分配给相应的簇。
4. 处理噪声
任何既不是核心点也不是边界点的数据点被标记为噪声。
数学公式
设我们有一个数据集 { x 1 , x 2 , . . . , x n } \{x_1, x_2, ..., x_n\} {x1,x2,...,xn}其中 x i ∈ R d x_i \in \mathbb{R}^d xi∈Rd 表示 d d d 维空间中的点。 邻域定义对于点 x i x_i xi其在 E p s Eps Eps 范围内的邻域定义为 N E p s ( x i ) { x j : d i s t ( x i , x j ) ≤ E p s } N_{Eps}(x_i) \{x_j : dist(x_i, x_j) \leq Eps\} NEps(xi){xj:dist(xi,xj)≤Eps} 这里 d i s t ( x i , x j ) dist(x_i, x_j) dist(xi,xj) 表示两点之间的距离度量如欧几里得距离。 核心点条件如果 ∣ N E p s ( x i ) ∣ ≥ M i n P t s |N_{Eps}(x_i)| \geq MinPts ∣NEps(xi)∣≥MinPts则 x i x_i xi 是核心点。 直接密度可达如果存在一个点 p p p 和一个点 q q q使得 q ∈ N E p s ( p ) q \in N_{Eps}(p) q∈NEps(p) 并且 p p p 是核心点则称 q q q 直接密度可达于 p p p。 密度可达如果存在一个点序列 p 1 , p 2 , . . . , p n p_1, p_2, ..., p_n p1,p2,...,pn使得对于每一个 i n i n in p i 1 p_{i1} pi1 直接密度可达于 p i p_i pi则称 p n p_n pn 密度可达于 p 1 p_1 p1。 密度相连如果存在一个点 o o o使得 p p p 和 q q q 都密度可达于 o o o则称 p p p 和 q q q 密度相连。
收敛性与复杂度
DBSCAN 算法不需要迭代优化而是通过单次扫描数据集来完成聚类。一旦所有点都被处理过算法自然结束。由于它不依赖于随机初始化或收敛标准因此不会陷入局部最优问题。 时间复杂度最坏情况下DBSCAN 的时间复杂度为 O ( n 2 ) O(n^2) O(n2)因为每个点都需要计算与其他所有点的距离。然而在实践中通过使用空间索引结构如 kd-tree 或 R-tree可以显著降低复杂度至 O ( n log n ) O(n \log n) O(nlogn)。 空间复杂度主要取决于存储数据点及其邻域信息所需的空间。
缺点与限制
尽管 DBSCAN 有许多优点但它也有一些局限性
参数敏感性对参数 E p s Eps Eps 和 M i n P t s MinPts MinPts 的选择非常敏感。不同参数设置可能导致不同的聚类结果特别是当簇密度差异较大时。高维数据挑战在高维空间中表现不佳因为距离度量变得不太有意义导致难以正确识别簇。计算资源需求对于大规模数据集计算所有点之间的距离可能需要大量的内存和计算时间。处理大小和密度变化的簇如果数据集中存在不同大小和密度的簇DBSCAN 可能无法同时捕捉所有类型的簇。
实际应用中的考虑
在实际应用中选择合适的 E p s Eps Eps 和 M i n P t s MinPts MinPts 参数至关重要。可以通过可视化方法或者基于领域知识来估计合理的参数值。此外为了提高效率可以使用近似最近邻搜索算法如 LSH 或 annoy来加速距离计算。最后对于非常高维的数据降维技术如 PCA 或 t-SNE可以帮助改善 DBSCAN 的性能。
当然接下来我将详细介绍基于层次的聚类算法——AGNESAgglomerative Nesting这是一种自底向上的层次聚类方法。与 K-Means 和 DBSCAN 不同AGNES 通过逐步合并最相似的簇来构建一个簇的层级结构。以下是关于 AGNES 算法的详细理论介绍包括其工作原理、数学公式和一些关键概念。
基于层次的聚类算法——AGNES 算法
AGNES 是一种层次聚类算法它从每个数据点作为一个独立的簇开始然后在每次迭代中合并两个最相似的簇直到满足某种停止条件。这种自底向上的过程最终会形成一个包含所有数据点的单一簇并生成一个描述簇合并历史的树状图dendrogram。
数学表示与关键概念
初始设置
数据集设我们有一个数据集 { x 1 , x 2 , . . . , x n } \{x_1, x_2, ..., x_n\} {x1,x2,...,xn}其中 x i ∈ R d x_i \in \mathbb{R}^d xi∈Rd 表示 d d d 维空间中的点。初始簇每个数据点最初被视为一个单独的簇。
距离度量与相似性度量
为了衡量两个簇之间的相似性或距离通常使用以下几种方法之一 单链接法Single Linkage D m i n ( C i , C j ) min x ∈ C i , y ∈ C j d ( x , y ) D_{min}(C_i, C_j) \min_{x \in C_i, y \in C_j} d(x, y) Dmin(Ci,Cj)x∈Ci,y∈Cjmind(x,y) 这里 d ( x , y ) d(x, y) d(x,y) 是两点之间的距离度量如欧几里得距离。 全链接法Complete Linkage D m a x ( C i , C j ) max x ∈ C i , y ∈ C j d ( x , y ) D_{max}(C_i, C_j) \max_{x \in C_i, y \in C_j} d(x, y) Dmax(Ci,Cj)x∈Ci,y∈Cjmaxd(x,y) 平均链接法Average Linkage D a v g ( C i , C j ) 1 ∣ C i ∣ ∣ C j ∣ ∑ x ∈ C i ∑ y ∈ C j d ( x , y ) D_{avg}(C_i, C_j) \frac{1}{|C_i||C_j|}\sum_{x \in C_i}\sum_{y \in C_j} d(x, y) Davg(Ci,Cj)∣Ci∣∣Cj∣1x∈Ci∑y∈Cj∑d(x,y) 中心链接法Centroid Linkage D c e n t r o i d ( C i , C j ) d ( μ i , μ j ) D_{centroid}(C_i, C_j) d(\mu_i, \mu_j) Dcentroid(Ci,Cj)d(μi,μj) 这里 μ i \mu_i μi 和 μ j \mu_j μj 分别是簇 C i C_i Ci 和 C j C_j Cj 的质心。
算法步骤
AGNES 算法的基本流程如下
1. 初始化
将每个数据点视为一个单独的簇初始化簇集合为 { { x 1 } , { x 2 } , . . . , { x n } } \{\{x_1\}, \{x_2\}, ..., \{x_n\}\} {{x1},{x2},...,{xn}}。
2. 计算距离矩阵
构建一个距离矩阵 D D D其中元素 D [ i ] [ j ] D[i][j] D[i][j] 表示簇 C i C_i Ci 和簇 C j C_j Cj 之间的距离根据所选的距离度量方法计算。
3. 合并最近的簇
在每次迭代中找到距离最小的一对簇 C i C_i Ci 和 C j C_j Cj 并将其合并成一个新的簇 C k C i ∪ C j C_k C_i \cup C_j CkCi∪Cj。更新距离矩阵 D D D移除旧的行和列对应于 C i C_i Ci 和 C j C_j Cj并在新位置插入新的行和列对应于 C k C_k Ck。
4. 重复合并
重复上述合并操作直到满足某个停止条件例如只剩下 k k k 个簇或者形成了一个单一的大簇。
5. 结果解释
最终结果可以是一个由多个簇组成的分层结构也可以通过切割 dendrogram 来获得特定数量的非嵌套簇。
收敛性与复杂度 时间复杂度最坏情况下AGNES 的时间复杂度为 O ( n 3 ) O(n^3) O(n3)因为每次合并后都需要重新计算所有簇之间的距离。然而在实践中可以通过优化技术如提前终止策略来减少实际计算量。 空间复杂度主要取决于存储距离矩阵和簇信息所需的空间。对于大型数据集可能需要考虑内存优化方案。
缺点与限制
尽管 AGNES 具有灵活性和直观性但它也有一些局限性
对异常值敏感特别是使用单链接法时容易受到噪声点的影响导致“链式效应”即形成细长的簇。难以处理大规模数据由于其高时间复杂度对于非常大的数据集AGNES 可能变得不切实际。参数选择虽然不需要预先指定簇的数量但如何选择合适的停止条件或切割高度仍然是一个挑战。不可逆性一旦进行了合并操作就不能撤销这可能导致局部最优解而不是全局最优解。
实际应用中的考虑
在实际应用中选择合适的距离度量方法非常重要。此外为了提高效率可以在早期阶段使用近似方法来加速距离计算。对于非常高维的数据降维技术如 PCA 或 t-SNE可以帮助改善 AGNES 的性能。最后通过可视化 dendrogram用户可以直观地选择适当的切割高度以获取所需的簇数。
基于网格的聚类算法——STINGStatistical Information Grid和 CLIQUEClustering In QUEst
基于网格的聚类算法概述
基于网格的聚类算法是一种高效的聚类方法它通过将整个数据空间划分为若干个非重叠的单元格或网格然后根据这些单元格内的数据密度来确定簇的位置和形状。这种方法不仅能够快速处理大规模数据集而且对于高维数据也能表现出色。与传统的层次聚类或划分式聚类相比基于网格的方法具有计算复杂度低、易于实现等优点。
STING 算法
概念与原理
STINGStatistical Information Grid 是一种典型的基于网格的聚类算法它使用统计信息来描述每个网格单元中的数据分布情况。STING 采用多分辨率的方式首先在较低分辨率下进行聚类然后逐步细化到更高分辨率直到达到所需的精度水平。
网格化将数据空间划分为多个层次的网格每一层由更小的单元格组成。统计信息为每个网格单元存储统计信息如平均值、方差、最大最小值等。查询处理用户可以通过指定条件例如密度阈值来进行聚类查询STING 根据存储的统计信息快速返回结果。
数学公式与关键概念 网格划分设 D D D 表示数据空间 G G G 表示网格结构则有 G { g 1 , g 2 , . . . , g m } G \{g_1, g_2, ..., g_m\} G{g1,g2,...,gm} 其中 g i g_i gi 表示第 i i i 个网格单元。 单元格统计信息对于每个单元格 g i g_i gi记录其统计信息 S ( g i ) S(g_i) S(gi)包括但不限于 平均值 μ ( g i ) \mu(g_i) μ(gi)方差 σ 2 ( g i ) \sigma^2(g_i) σ2(gi)最大值 m a x ( g i ) max(g_i) max(gi) 和最小值 m i n ( g i ) min(g_i) min(gi)数据点数量 n ( g i ) n(g_i) n(gi) 密度计算定义单元格 g i g_i gi 的密度为 d e n s i t y ( g i ) n ( g i ) v o l ( g i ) density(g_i) \frac{n(g_i)}{vol(g_i)} density(gi)vol(gi)n(gi) 这里 v o l ( g i ) vol(g_i) vol(gi) 表示单元格的体积。 层次遍历从顶层开始递归地检查子单元格是否满足给定的密度阈值 θ \theta θ。如果某个单元格的密度大于等于 θ \theta θ则进一步细分为更小的子单元格否则标记为非密集区域。
算法步骤
初始化构建初始的粗粒度网格并为每个单元格计算统计信息。多分辨率分析按照设定的密度阈值自顶向下逐层细化网格直到找到所有满足条件的密集区域。结果输出输出最终确定的簇列表及其对应的网格单元。
CLIQUE 算法
概念与原理
CLIQUEClustering In QUEst 是另一种基于网格的聚类算法它特别适合处理高维数据。CLIQUE 不仅可以识别任意形状的簇还能有效处理噪声数据。它的核心思想是通过检测不同维度上的稠密单元格组合来发现潜在的簇。
子空间划分将每个维度独立地划分为若干个区间bins形成一个多维网格。稠密单元格检测对于每一个可能的子空间组合检查其中的单元格是否足够密集。簇生成连接相邻的稠密单元格以形成簇并通过投影技术减少维度的影响。
数学公式与关键概念 子空间划分设 D D D 为 d d d 维数据空间 B i B_i Bi 表示第 i i i 维上的区间集合则有 B i { b i 1 , b i 2 , . . . , b i k } B_i \{b_{i1}, b_{i2}, ..., b_{ik}\} Bi{bi1,bi2,...,bik} 每个 b i j b_{ij} bij 定义了一个特定范围。 稠密度计算定义单元格 ( b 1 j 1 , b 2 j 2 , . . . , b d j d ) (b_{1j_1}, b_{2j_2}, ..., b_{dj_d}) (b1j1,b2j2,...,bdjd) 的稠密度为 d e n s i t y ( b 1 j 1 , b 2 j 2 , . . . , b d j d ) n ( b 1 j 1 , b 2 j 2 , . . . , b d j d ) v o l ( b 1 j 1 , b 2 j 2 , . . . , b d j d ) density(b_{1j_1}, b_{2j_2}, ..., b_{dj_d}) \frac{n(b_{1j_1}, b_{2j_2}, ..., b_{dj_d})}{vol(b_{1j_1}, b_{2j_2}, ..., b_{dj_d})} density(b1j1,b2j2,...,bdjd)vol(b1j1,b2j2,...,bdjd)n(b1j1,b2j2,...,bdjd) 显著性检验引入显著性水平 α \alpha α 来判断单元格是否为稠密单元格。如果一个单元格的稠密度超过 α \alpha α则认为它是稠密的。 邻接关系两个单元格被认为是邻接的当且仅当它们在所有维度上都相邻或者至少有一个公共边界。 簇生成通过连接所有邻接的稠密单元格形成最终的簇。
算法步骤
初始化对每个维度分别进行等宽划分创建初始的多维网格。稠密单元格检测遍历所有可能的子空间组合找出所有稠密单元格。簇生成连接相邻的稠密单元格形成簇。降维优化通过投影技术减少不必要的维度提高效率。结果输出输出最终确定的簇列表及其对应的稠密单元格。
收敛性与复杂度 时间复杂度由于基于网格的方法通常只需要一次扫描数据集因此它们的时间复杂度相对较低通常是线性的 O ( n ) O(n) O(n) 或者接近线性的 O ( n log n ) O(n \log n) O(nlogn)。 空间复杂度主要取决于存储网格结构和相关统计信息所需的空间。对于非常大的数据集可能需要考虑内存优化方案。
缺点与限制
尽管基于网格的聚类算法有许多优点但也存在一些局限性
参数敏感性对网格大小的选择非常敏感不同的网格尺寸可能导致不同的聚类结果。处理稀疏数据困难在某些情况下特别是在高维空间中可能会出现很多空单元格导致算法效率下降。难以捕捉复杂形状的簇虽然 CLIQUE 能够处理任意形状的簇但对于非常复杂的簇形态基于网格的方法仍然可能不够灵活。依赖预处理为了获得最佳性能通常需要对数据进行适当的预处理如标准化或特征选择。
基于模型的聚类算法——高斯混合模型Gaussian Mixture Model, GMM
GMM 是一种概率模型用于描述由多个高斯分布组成的复杂数据分布。每个高斯分布代表一个潜在的簇而 GMM 的目标是找到最能解释观测数据的混合高斯分布参数。与 K-Means 不同GMM 可以捕捉簇之间的重叠部分并且能够处理不同形状和大小的簇。
数学表示与关键概念
模型定义
设我们有一个数据集 { x 1 , x 2 , . . . , x n } \{x_1, x_2, ..., x_n\} {x1,x2,...,xn}其中 x i ∈ R d x_i \in \mathbb{R}^d xi∈Rd 表示 d d d 维空间中的点。GMM 假设这些数据点是从 K K K 个高斯分布中生成的每个分布由均值向量 μ k \mu_k μk、协方差矩阵 Σ k \Sigma_k Σk 和混合系数 π k \pi_k πk 描述满足 ∑ k 1 K π k 1 \sum_{k1}^{K} \pi_k 1 k1∑Kπk1
每个数据点的概率密度函数可以表示为 p ( x i ) ∑ k 1 K π k N ( x i ∣ μ k , Σ k ) p(x_i) \sum_{k1}^{K} \pi_k \mathcal{N}(x_i | \mu_k, \Sigma_k) p(xi)k1∑KπkN(xi∣μk,Σk)
这里 N ( x i ∣ μ k , Σ k ) \mathcal{N}(x_i | \mu_k, \Sigma_k) N(xi∣μk,Σk) 是高斯分布的概率密度函数定义为 N ( x i ∣ μ k , Σ k ) 1 ( 2 π ) d / 2 ∣ Σ k ∣ 1 / 2 exp ( − 1 2 ( x i − μ k ) T Σ k − 1 ( x i − μ k ) ) \mathcal{N}(x_i | \mu_k, \Sigma_k) \frac{1}{(2\pi)^{d/2} |\Sigma_k|^{1/2}} \exp\left(-\frac{1}{2}(x_i - \mu_k)^T \Sigma_k^{-1} (x_i - \mu_k)\right) N(xi∣μk,Σk)(2π)d/2∣Σk∣1/21exp(−21(xi−μk)TΣk−1(xi−μk))
参数估计
为了估计 GMM 的参数通常使用期望最大化Expectation-Maximization, EM算法。EM 算法通过迭代优化过程来最大化数据的对数似然函数 L ( θ ) ∑ i 1 n log p ( x i ∣ θ ) ∑ i 1 n log ∑ k 1 K π k N ( x i ∣ μ k , Σ k ) L(\theta) \sum_{i1}^{n} \log p(x_i | \theta) \sum_{i1}^{n} \log \sum_{k1}^{K} \pi_k \mathcal{N}(x_i | \mu_k, \Sigma_k) L(θ)i1∑nlogp(xi∣θ)i1∑nlogk1∑KπkN(xi∣μk,Σk)
这里 θ ( μ 1 , Σ 1 , π 1 , . . . , μ K , Σ K , π K ) \theta (\mu_1, \Sigma_1, \pi_1, ..., \mu_K, \Sigma_K, \pi_K) θ(μ1,Σ1,π1,...,μK,ΣK,πK) 表示所有未知参数。
EM 算法步骤
EM 算法分为两个主要步骤E 步Expectation Step和 M 步Maximization Step这两个步骤交替进行直到收敛。
1. 初始化
随机初始化或使用某种启发式方法设置初始参数 θ ( 0 ) ( μ k ( 0 ) , Σ k ( 0 ) , π k ( 0 ) ) \theta^{(0)} (\mu_k^{(0)}, \Sigma_k^{(0)}, \pi_k^{(0)}) θ(0)(μk(0),Σk(0),πk(0))。
2. E 步期望步
对于每个数据点 x i x_i xi 和每个高斯分布 k k k计算后验概率也称为责任度responsibility γ ( z i k ) π k ( t ) N ( x i ∣ μ k ( t ) , Σ k ( t ) ) ∑ j 1 K π j ( t ) N ( x i ∣ μ j ( t ) , Σ j ( t ) ) \gamma(z_{ik}) \frac{\pi_k^{(t)} \mathcal{N}(x_i | \mu_k^{(t)}, \Sigma_k^{(t)})}{\sum_{j1}^{K} \pi_j^{(t)} \mathcal{N}(x_i | \mu_j^{(t)}, \Sigma_j^{(t)})} γ(zik)∑j1Kπj(t)N(xi∣μj(t),Σj(t))πk(t)N(xi∣μk(t),Σk(t))
3. M 步最大化步
更新参数以最大化对数似然函数 μ k ( t 1 ) ∑ i 1 n γ ( z i k ) x i ∑ i 1 n γ ( z i k ) \mu_k^{(t1)} \frac{\sum_{i1}^{n} \gamma(z_{ik}) x_i}{\sum_{i1}^{n} \gamma(z_{ik})} μk(t1)∑i1nγ(zik)∑i1nγ(zik)xi Σ k ( t 1 ) ∑ i 1 n γ ( z i k ) ( x i − μ k ( t 1 ) ) ( x i − μ k ( t 1 ) ) T ∑ i 1 n γ ( z i k ) \Sigma_k^{(t1)} \frac{\sum_{i1}^{n} \gamma(z_{ik}) (x_i - \mu_k^{(t1)}) (x_i - \mu_k^{(t1)})^T}{\sum_{i1}^{n} \gamma(z_{ik})} Σk(t1)∑i1nγ(zik)∑i1nγ(zik)(xi−μk(t1))(xi−μk(t1))T π k ( t 1 ) ∑ i 1 n γ ( z i k ) n \pi_k^{(t1)} \frac{\sum_{i1}^{n} \gamma(z_{ik})}{n} πk(t1)n∑i1nγ(zik)
4. 迭代
重复执行 E 步和 M 步直到参数变化小于某个阈值或者达到最大迭代次数。
收敛性与复杂度 时间复杂度每次迭代的时间复杂度为 O ( n K d 2 ) O(nKd^2) O(nKd2)其中 n n n 是数据点数量 K K K 是高斯分布的数量 d d d 是特征维度。 空间复杂度主要取决于存储数据点、参数以及中间变量所需的空间。
缺点与限制
尽管 GMM 具有灵活性和强大表达能力但它也有一些局限性
过拟合风险如果选择过多的高斯成分可能会导致过拟合问题。因此需要合理选择 K K K 的值。局部最优解EM 算法容易陷入局部最优解特别是当初始参数选择不当的时候。计算成本较高对于大规模数据集计算协方差矩阵及其逆矩阵可能非常耗时。敏感于异常值由于使用了欧几里得距离GMM 对异常值较为敏感。
总结
在实际应用中选择合适的 K K K 值非常重要。可以通过交叉验证或信息准则如 AIC 或 BIC来确定最佳的簇数。此外为了提高效率可以在早期阶段使用近似方法来加速 EM 算法的收敛。对于非常高维的数据降维技术如 PCA 或 t-SNE可以帮助改善 GMM 的性能。最后通过可视化工具用户可以直观地探索和理解聚类结果。
聚类算法实战——K-Means算法——购物中心客户分群分析
业务背景
某大型购物中心希望通过数据分析来更好地了解他们的客户群体以便制定更有针对性的营销策略和服务方案。通过收集客户的年收入数据和消费积分根据购物频率和金额计算我们使用K-Means聚类算法来识别不同的客户群体。
仿真数据说明
在这个购物中心客户分群分析中我们总共生成了300个客户样本数据均匀分为三组每组包含100个客户。数据包含两个特征年收入和消费积分。使用正态分布np.random.normal生成数据这样可以更好地模拟真实世界中的数据分布特征。
第一组是高收入高消费群体年收入均值为80,000元标准差10,000元消费积分均值为90分标准差20分代表着购物中心的高端客户群。第二组是中等收入中等消费群体年收入均值为45,000元标准差8,000元消费积分均值为50分标准差15分这代表了主流消费群体。第三组是低收入低消费群体年收入均值为25,000元标准差5,000元消费积分均值为30分标准差10分代表预算型消费者。
通过合理设置均值和标准差我们确保了三个群体之间既有明显的特征差异又存在适度的重叠这更符合现实情况。收入范围大致在15,000至100,000元之间消费积分范围在0-100分之间。使用np.random.seed(42)确保了数据的可重复性便于进行算法验证和结果复现。这样的数据设计既保证了群体特征的可区分性又保持了数据分布的自然性和现实性非常适合用来展示K-Means聚类算法的效果。仿真数据可视化效果如下图一所示。
其中用到的几个数据说明
年收入客户的年收入数据单位元消费积分基于客户的购物行为计算的积分考虑因素购物频率、单次消费金额、会员等级等积分范围0-100分
图一 原始数据 聚类目标
将客户分为三个主要群体
高价值客户群高收入、高消费积分 特点年收入约8万元消费积分90分左右 营销策略提供高端产品推荐、VIP服务、专属活动中等价值客户群中等收入、中等消费积分 特点年收入约4.5万元消费积分50分左右 营销策略提供性价比产品、会员优惠、促销活动潜力客户群较低收入、较低消费积分 特点年收入约2.5万元消费积分30分左右 营销策略提供特惠商品、入门级产品推荐、积分奖励计划
商业价值
1精准营销 根据不同群体特征制定差异化营销策略提高营销效率降低营销成本 2库存管理 根据不同群体的消费能力调整商品结构优化库存水平提高周转率 3服务优化为不同群体提供差异化服务提升客户满意度和忠诚度 4商业决策为新店选址提供数据支持指导商品采购和定价策略
通过这个分析购物中心可以
更好地理解客户构成制定更有针对性的营销策略优化商品结构和服务体系提高经营效率和客户满意度
使用K-Means解决问题
为了解决购物中心客户分群的问题我们使用K-Means聚类算法进行分析。首先对原始数据进行标准化处理使用StandardScaler这样可以消除不同特征年收入和消费积分之间的尺度差异使得聚类结果更加准确。K-Means算法通过迭代的方式将数据点划分为k个簇在本案例中k3每个簇由其质心中心点表示。算法的核心思想是最小化每个数据点到其所属簇中心的平方距离之和。
在实现过程中我们使用了sklearn.cluster中的KMeans类设置random_state42以确保结果可重现。算法首先随机初始化三个聚类中心然后反复进行两个步骤将每个数据点分配给最近的聚类中心然后重新计算每个簇的中心位置。这个过程会不断重复直到聚类中心的位置基本稳定或达到最大迭代次数。为了可视化聚类效果我们绘制了散点图和箱型图图二所示其中散点图展示了不同类别的空间分布和聚类中心箱型图则显示了各个簇在收入和消费积分上的统计特征帮助我们更好地理解每个客户群体的特点。
图二 聚类后的数据 
图三 聚类后的详细信息 根据图二可知左侧的聚类散点图显示K-Means算法成功地将客户分成了三个相对独立的群体。红色的聚类中心点很好地捕捉到了各个群体的中心位置表明算法的聚类效果理想。从空间分布来看三个类别的边界相对清晰但仍保持着适度的重叠这符合实际业务场景中客户群体的特征。
右侧的箱型图详细展示了各个聚类在收入和消费两个维度上的分布特征
各群体的中位数箱型图中的横线呈现明显的层次差异验证了聚类的有效性箱体的高度反映了数据的离散程度表明高收入群体的数据波动较大而低收入群体相对集中少量的离群点箱型图上的点表明存在一些特殊的客户案例这对制定个性化营销策略有重要参考价值
总的来说聚类结果很好地反映了客户群体的自然分层现象为购物中心制定差异化的营销策略和服务方案提供了可靠的数据支持。这种基于数据的客户分群方法能够帮助商家更精准地了解客户特征从而提供更有针对性的服务。这里也是用了DBSCAN进行聚类但是效果不太好大家有兴趣的可以自己去试一下代码下面有提供。
完整代码——K-Means
import numpy as np
import matplotlib
matplotlib.use(Agg) # 设置后端为Agg
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import os
from matplotlib import font_manager# 设置线程数以避免内存泄漏警告
os.environ[OMP_NUM_THREADS] 2# 设置中文字体
plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签
plt.rcParams[axes.unicode_minus] False # 用来正常显示负号# 生成模拟数据
np.random.seed(42)# 生成三个不同的客户群体数据
n_samples 300# 高收入高消费群体
income_1 np.random.normal(80000, 10000, n_samples//3)
spending_1 np.random.normal(90, 20, n_samples//3)# 中等收入中等消费群体
income_2 np.random.normal(45000, 8000, n_samples//3)
spending_2 np.random.normal(50, 15, n_samples//3)# 低收入低消费群体
income_3 np.random.normal(25000, 5000, n_samples//3)
spending_3 np.random.normal(30, 10, n_samples//3)# 合并数据
X np.vstack([np.column_stack((income_1, spending_1)),np.column_stack((income_2, spending_2)),np.column_stack((income_3, spending_3))
])# 绘制原始数据分布图
plt.figure(figsize(10, 6))
colors [#FF9999, #66B2FF, #99FF99]
labels [高收入高消费群体, 中等收入消费群体, 低收入低消费群体]# 分别绘制三个群体的散点图
plt.scatter(income_1, spending_1, ccolors[0], labellabels[0], alpha0.6)
plt.scatter(income_2, spending_2, ccolors[1], labellabels[1], alpha0.6)
plt.scatter(income_3, spending_3, ccolors[2], labellabels[2], alpha0.6)plt.xlabel(年收入 (元))
plt.ylabel(消费积分)
plt.title(购物中心客户原始数据分布)
plt.legend()
plt.grid(True, linestyle--, alpha0.7)# 保存原始数据分布图
plt.savefig(original_data_distribution.png, dpi300, bbox_inchestight)
plt.close()# 数据标准化
scaler StandardScaler()
X_scaled scaler.fit_transform(X)# 使用K-Means进行聚类
kmeans KMeans(n_clusters3, random_state42)
clusters kmeans.fit_predict(X_scaled)# 创建一个图形包含两个子图
plt.figure(figsize(15, 6))# 1. 散点图显示聚类结果
plt.subplot(1, 2, 1)
scatter plt.scatter(X[:, 0], X[:, 1], cclusters, cmapviridis)
plt.xlabel(年收入 (元))
plt.ylabel(消费积分)
plt.title(购物中心客户分群散点图)
plt.colorbar(scatter)# 添加聚类中心
centers scaler.inverse_transform(kmeans.cluster_centers_)
plt.scatter(centers[:, 0], centers[:, 1], cred, markerx, s200, linewidths3, label聚类中心)
plt.legend()# 2. 箱型图显示每个聚类的收入和消费分布
plt.subplot(1, 2, 2)
cluster_data []
labels []
for i in range(3):cluster_data.extend([X[clusters i, 0], X[clusters i, 1]])labels.extend([f聚类{i1}-收入, f聚类{i1}-消费])plt.boxplot(cluster_data, labelslabels)
plt.xticks(rotation45)
plt.title(各聚类群体的收入和消费分布)
plt.ylabel(数值)# 调整布局并保存图形
plt.tight_layout()
plt.savefig(customer_segmentation.png, dpi300, bbox_inchestight)# 打印每个聚类的基本统计信息
for i in range(3):cluster_data X[clusters i]print(f\n聚类 {i1} 的统计信息)print(f样本数量: {len(cluster_data)})print(f平均年收入: {cluster_data[:, 0].mean():.2f} 元)print(f平均消费积分: {cluster_data[:, 1].mean():.2f})print(f收入标准差: {cluster_data[:, 0].std():.2f})print(f消费积分标准差: {cluster_data[:, 1].std():.2f})
完整代码——DBSCAN
import numpy as np
import matplotlib
matplotlib.use(Agg)
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
import os# 设置中文字体
plt.rcParams[font.sans-serif] [SimHei]
plt.rcParams[axes.unicode_minus] False# 生成模拟数据
np.random.seed(42)
n_samples 300# 生成环形数据代表高端客户群年收入高消费较分散
radius1 80000
theta1 np.random.uniform(0, 2*np.pi, n_samples//3)
income_1 radius1 * np.cos(theta1) 90000
spending_1 radius1 * np.sin(theta1)*0.001 80# 生成集中分布数据代表中端客户群
income_2 np.random.normal(50000, 8000, n_samples//3)
spending_2 np.random.normal(50, 10, n_samples//3)# 生成条带形数据代表低端客户群收入跨度大消费相对固定
income_3 np.random.uniform(20000, 40000, n_samples//3)
spending_3 np.random.normal(30, 5, n_samples//3)# 合并数据
X np.vstack([np.column_stack((income_1, spending_1)),np.column_stack((income_2, spending_2)),np.column_stack((income_3, spending_3))
])# 绘制原始数据分布图
plt.figure(figsize(10, 6))
colors [#FF9999, #66B2FF, #99FF99]
labels [高端客户群环形分布, 中端客户群集中分布, 低端客户群条带分布]# 分别绘制三个群体的散点图
plt.scatter(income_1, spending_1, ccolors[0], labellabels[0], alpha0.6)
plt.scatter(income_2, spending_2, ccolors[1], labellabels[1], alpha0.6)
plt.scatter(income_3, spending_3, ccolors[2], labellabels[2], alpha0.6)plt.xlabel(年收入 (元))
plt.ylabel(消费积分)
plt.title(购物中心客户原始数据分布非球形簇)
plt.legend()
plt.grid(True, linestyle--, alpha0.7)# 保存原始数据分布图
plt.savefig(dbscan_original_distribution.png, dpi300, bbox_inchestight)
plt.close()# 数据标准化
scaler StandardScaler()
X_scaled scaler.fit_transform(X)# 使用DBSCAN进行聚类
dbscan DBSCAN(eps0.3, min_samples10)
clusters dbscan.fit_predict(X_scaled)# 创建一个图形包含两个子图
plt.figure(figsize(15, 6))# 1. 散点图显示聚类结果
plt.subplot(1, 2, 1)
scatter plt.scatter(X[:, 0], X[:, 1], cclusters, cmapviridis)
plt.xlabel(年收入 (元))
plt.ylabel(消费积分)
plt.title(DBSCAN客户分群结果)
plt.colorbar(scatter)# 2. 各群体的消费特征分布图
plt.subplot(1, 2, 2)
valid_clusters clusters[clusters ! -1] # 排除噪声点
valid_data X[clusters ! -1]# 为每个聚类计算并显示核密度估计
for cluster_id in np.unique(valid_clusters):cluster_data valid_data[valid_clusters cluster_id]plt.hist(cluster_data[:, 1], bins20, alpha0.5, labelf群体 {cluster_id1}, densityTrue)plt.xlabel(消费积分)
plt.ylabel(密度)
plt.title(各客户群体消费特征分布)
plt.legend()# 调整布局并保存图形
plt.tight_layout()
plt.savefig(dbscan_clustering_result.png, dpi300, bbox_inchestight)# 打印每个聚类的基本统计信息
print(\n聚类统计信息)
print(f识别出的群体数量: {len(np.unique(clusters))})
print(f噪声点数量: {np.sum(clusters -1)})for cluster_id in np.unique(clusters):if cluster_id -1:continuecluster_data X[clusters cluster_id]print(f\n群体 {cluster_id1} 的统计信息)print(f样本数量: {len(cluster_data)})print(f平均年收入: {cluster_data[:, 0].mean():.2f} 元)print(f平均消费积分: {cluster_data[:, 1].mean():.2f})print(f收入标准差: {cluster_data[:, 0].std():.2f})print(f消费积分标准差: {cluster_data[:, 1].std():.2f})
聚类算法实战——DBSCAN算法——城市公共自行车站点分布分析
业务背景
随着绿色出行理念的普及城市公共自行车系统已成为城市交通网络中不可或缺的一部分。某城市正在评估其公共自行车系统的运营效果希望通过数据分析来优化站点布局和运营策略。系统中的每个站点都配备了智能监测设备可以实时记录自行车的借还情况从而计算出站点的使用率。
数据说明
在这个分析中我们生成了300个自行车站点的数据包含三个关键特征
地理位置 经度坐标 纬度坐标使用率站点日均使用率0-100% 计算方式日均租还次数/站点容量 反映站点的实际使用情况
数据按照区域特征可以大致分为三类
商业区站点 特点密集分布使用率高均值80%标准差10% 位置城市中心区域 使用模式工作日高峰明显双向流动住宅区站点 特点分散分布使用率中等均值50%标准差15% 位置城市居住区 使用模式早晚高峰单向流动为主景区站点 特点带状分布使用率波动大均值60%标准差20% 位置沿城市景观带分布 使用模式周末和节假日使用率高
仿真数据可视化之后如下图四所示
图四 原始数据分布 分析目标
1站点群组识别发现自然形成的站点集群、识别孤立的站点、分析不同区域的使用特征 2运营优化优化自行车重分配策略、调整站点容量配置、识别需要新增或调整的站点位置 3服务提升提高车辆周转率、减少用户等待时间、提升系统运营效率
分析价值
1资源配置优化根据使用率调整站点容量、优化车辆调度路线、合理分配维护资源 2运营效率提升减少空置和爆满情况、降低运维成本、提高用户满意度 3规划决策支持指导新站点选址、优化现有站点布局、制定差异化运营策略 4可持续发展促进绿色出行、提高系统使用效率、减少碳排放
使用DBSCAN解决问题
为了解决城市公共自行车站点分布分析问题我们使用DBSCAN基于密度的空间聚类算法进行分析。首先对包含经度、纬度和使用率的三维数据进行标准化处理使用StandardScaler以消除不同特征之间的尺度差异。DBSCAN算法通过设置邻域半径eps0.3和最小样本数min_samples5两个关键参数基于密度的连通性自动识别站点群组。该算法的核心思想是找到密度相连的区域将其划分为一个聚类同时将密度不足的点标记为噪声点。这种方法特别适合我们的场景因为它不需要预先指定群组数量能够发现任意形状的站点集群并且可以自动识别独立的、可能需要特殊关注的站点。为了直观地展示分析结果我们通过散点图展示聚类的空间分布点的大小表示使用率并使用箱型图分析各群组的使用率分布特征这样的可视化有助于我们理解不同区域的站点使用模式和特点。代码运行之后结果如下图五图六所示。 图五 DBSCAN聚类结果 图六 每个组群的信息 DBSCAN算法在城市自行车站点分析中识别出了8个主要群组和161个噪声点其中最显著的是群组1包含81个站点主要分布在城市核心区域经度4.02-5.78纬度4.04-6.10具有最高的平均使用率79.86%和较为稳定的使用模式标准差7.88%而群组8虽然仅有9个站点但同样表现出高使用率76.80%和稳定性标准差5.00%这两个群组可能代表了重要的商业或交通枢纽区域。其他群组2-7的站点数量较少5-18个不等使用率普遍在41%-56%之间标准差较小1.15%-5.34%表现出相对稳定的使用模式。
从聚类结果图图五中可以观察到左图显示了站点的空间分布特征其中高使用率的群组群组1和8在空间上形成了明显的集聚区域而其他群组则相对分散右图的箱型图展示了各群组的使用率分布清晰地反映出群组1和8与其他群组在使用率上的显著差异。值得注意的是超过一半的站点161个被识别为噪声点这表明城市自行车站点的分布存在较大的离散性这些孤立的站点可能需要进行位置调整或与周边站点进行优化整合。
完整代码
import numpy as np
import matplotlib
matplotlib.use(Agg)
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import StandardScaler
import os# 设置中文字体
plt.rcParams[font.sans-serif] [SimHei]
plt.rcParams[axes.unicode_minus] False# 生成模拟数据
np.random.seed(42)
n_samples 300# 生成商业区站点数据密集使用工作日高峰
business_x np.random.normal(5, 0.5, n_samples//3) # 经度
business_y np.random.normal(5, 0.5, n_samples//3) # 纬度
business_usage np.random.normal(80, 10, n_samples//3) # 使用率# 生成住宅区站点数据早晚高峰分散分布
residential_x np.random.normal(2, 1.5, n_samples//3)
residential_y np.random.normal(2, 1.5, n_samples//3)
residential_usage np.random.normal(50, 15, n_samples//3)# 生成景区站点数据周末高峰带状分布
scenic_x np.linspace(0, 8, n_samples//3) np.random.normal(0, 0.3, n_samples//3)
scenic_y np.sin(scenic_x) np.random.normal(0, 0.3, n_samples//3)
scenic_usage np.random.normal(60, 20, n_samples//3)# 合并数据
X np.vstack([np.column_stack((business_x, business_y, business_usage)),np.column_stack((residential_x, residential_y, residential_usage)),np.column_stack((scenic_x, scenic_y, scenic_usage))
])# 绘制原始数据分布图
plt.figure(figsize(12, 5))
plt.subplot(1, 2, 1)
colors [#FF9999, #66B2FF, #99FF99]
labels [商业区站点, 住宅区站点, 景区站点]# 绘制散点图点的大小根据使用率变化
plt.scatter(business_x, business_y, ccolors[0], sbusiness_usage, alpha0.6, labellabels[0])
plt.scatter(residential_x, residential_y, ccolors[1], sresidential_usage, alpha0.6, labellabels[1])
plt.scatter(scenic_x, scenic_y, ccolors[2], sscenic_usage, alpha0.6, labellabels[2])plt.xlabel(经度)
plt.ylabel(纬度)
plt.title(自行车站点分布点大小表示使用率)
plt.legend()
plt.grid(True, linestyle--, alpha0.7)# 使用率分布图
plt.subplot(1, 2, 2)
plt.hist([business_usage, residential_usage, scenic_usage], labellabels, colorcolors, alpha0.6, bins15)
plt.xlabel(站点使用率 (%))
plt.ylabel(站点数量)
plt.title(不同区域站点使用率分布)
plt.legend()# 保存原始数据分布图
plt.tight_layout()
plt.savefig(bike_stations_original.png, dpi300, bbox_inchestight)
plt.close()# 数据标准化
scaler StandardScaler()
X_scaled scaler.fit_transform(X)# 使用DBSCAN进行聚类
dbscan DBSCAN(eps0.3, min_samples5)
clusters dbscan.fit_predict(X_scaled)# 创建新图形展示聚类结果
plt.figure(figsize(12, 5))# 1. 散点图显示聚类结果
plt.subplot(1, 2, 1)
scatter plt.scatter(X[:, 0], X[:, 1], cclusters, sX[:, 2], cmapviridis)
plt.xlabel(经度)
plt.ylabel(纬度)
plt.title(DBSCAN聚类结果\n(点大小表示使用率))
plt.colorbar(scatter, label聚类编号)# 2. 各聚类的使用率箱型图
plt.subplot(1, 2, 2)
valid_clusters clusters[clusters ! -1]
valid_usage X[clusters ! -1, 2]# 为每个聚类创建箱型图
cluster_data []
labels []
for cluster_id in np.unique(valid_clusters):cluster_data.append(X[clusters cluster_id, 2])labels.append(f群组 {cluster_id1})plt.boxplot(cluster_data, labelslabels)
plt.xlabel(聚类群组)
plt.ylabel(使用率 (%))
plt.title(各聚类群组使用率分布)# 保存聚类结果图
plt.tight_layout()
plt.savefig(bike_stations_clusters.png, dpi300, bbox_inchestight)# 打印聚类统计信息
print(\n聚类统计信息)
print(f识别出的群组数量: {len(np.unique(clusters[clusters ! -1]))})
print(f噪声点数量: {np.sum(clusters -1)})for cluster_id in np.unique(clusters):if cluster_id -1:continuecluster_data X[clusters cluster_id]print(f\n群组 {cluster_id1} 的统计信息)print(f站点数量: {len(cluster_data)})print(f平均使用率: {cluster_data[:, 2].mean():.2f}%)print(f使用率标准差: {cluster_data[:, 2].std():.2f}%)print(f区域范围: 经度({cluster_data[:, 0].min():.2f}-{cluster_data[:, 0].max():.2f}), f纬度({cluster_data[:, 1].min():.2f}-{cluster_data[:, 1].max():.2f}))
总结
在这篇文章中我作为一位初学者尝试对聚类分析这一无监督学习领域进行了探索和总结。聚类分析旨在将数据点根据其相似性分成不同的簇从而揭示数据中的自然分组结构。文中详细介绍了几种主要的聚类算法包括基于划分的K-Means、基于密度的DBSCAN、基于层次的AGNES、基于网格的STING与CLIQUE以及基于模型的GMM并且探讨了每种算法的工作原理、数学公式、应用场景及其优缺点。
为了更好地理解这些理论知识我还通过两个实际案例来展示如何应用聚类算法解决现实问题
购物中心客户分群分析使用K-Means算法对客户的年收入和消费积分进行聚类以识别不同价值的客户群体为精准营销提供支持。城市公共自行车站点分布分析采用DBSCAN算法分析自行车站点的位置和使用率帮助优化站点布局和服务策略。
在撰写过程中我发现每个算法都有其独特的特性和适用范围选择合适的算法对于获得有效的聚类结果至关重要。同时我也意识到参数的选择如K-Means中的k值或DBSCAN中的Eps和MinPts对最终结果有着重要影响这需要结合具体的数据特征和业务需求来进行调整。
由于我还是聚类领域的初学者这篇文章仅代表我个人的理解和见解可能存在不准确或不够深入的地方。因此非常欢迎各位读者指出文章中的问题希望我们能够就此展开讨论互相学习共同进步。感谢大家的阅读和支持