news 2026/5/7 11:40:04

分裂式层次聚类:DIANA 算法的原理、实践与场景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分裂式层次聚类:DIANA 算法的原理、实践与场景

在无监督学习的聚类家族中,层次聚类以 “可解释的层级结构” 脱颖而出,而DIANA(Divisive Analysis)作为分裂式层次聚类的经典代表,靠 “从整体拆分为局部” 的思路,在细分场景中颇受欢迎。今天咱们深入聊聊 DIANA 的来龙去脉。

一、DIANA 算法的定义:什么是 “分裂式层次聚类”?

层次聚类分为凝聚式(Agglomerative)分裂式(Divisive)两类:

  • 凝聚式:从 “每个样本是一个簇” 开始,逐步合并相似的簇;
  • 分裂式:从 “所有样本是一个簇” 开始,逐步将簇拆分为更小的子簇。

DIANA 算法是分裂式层次聚类的典型实现,其核心逻辑是:通过 “迭代分裂最分散的簇”,生成从 “整体” 到 “细分” 的簇层级结构

二、DIANA 算法的作用:适合哪些场景?

DIANA 的 “分裂式” 特性,让它在以下场景中更具优势:

  1. 需要 “从粗到细” 的分类体系:比如企业客户分层(先拆为 “付费客户 / 免费客户”,再拆 “高付费 / 中付费”)、文档主题分类(先拆 “科技类 / 人文类”,再拆 “AI / 大数据”)。
  2. 样本量中等且追求可解释性:相比 K-Means 的 “黑箱式聚类”,DIANA 的分裂过程清晰(每一步都能解释 “为什么拆这个簇”),适合需要汇报聚类逻辑的场景。
  3. 探索性数据分析(EDA):可以先通过 DIANA 得到簇的层次结构,再确定最终的簇数量(比如从 “1 个大簇” 拆到 “5 个小簇”,观察哪一层的分类最合理)。

三、DIANA 算法的核心逻辑与细节

1. 算法的完整流程

DIANA 的分裂过程遵循严格的步骤,以 “簇的分散程度” 为核心判断依据:

其中关键概念:

  • 簇的直径:簇内任意两个样本的距离最大值(代表簇的 “分散程度”);
  • 分裂依据:待分裂簇中,“与其他样本平均距离最大” 的点,是新簇的核心(因为它和原簇的其他样本最不相似)。关于簇直径的计算细节,可以参考:聚类中常用的簇分散度指标。

2. 代码实现:更完整的 DIANA(含评估)

  • 我们基于 Python 实现完整的 DIANA,并加入轮廓系数评估:

    import numpy as np from scipy.spatial.distance import pdist, squareform from sklearn.metrics import silhouette_score def calculate_cluster_diameter(cluster_data): """计算簇的直径(簇内样本的最大距离)""" if len(cluster_data) <= 1: return 0 dist_matrix = squareform(pdist(cluster_data)) return np.max(dist_matrix) def select_split_point(cluster_data): """选择待分裂簇中“最远离其他样本”的点(平均距离最大)""" if len(cluster_data) == 1: return 0 dist_matrix = squareform(pdist(cluster_data)) avg_dist = np.mean(dist_matrix, axis=1) # 每个点到其他点的平均距离 return np.argmax(avg_dist) # 平均距离最大的点作为分裂点 def diana_complete(data, stop_condition='n_clusters', threshold=2): """ 完整DIANA实现 stop_condition: 停止条件('n_clusters'=簇数量;'diameter'=簇直径阈值) threshold: 停止条件对应的阈值 """ # 初始化簇:所有样本的索引组成1个簇 clusters = [list(range(len(data)))] while True: # 1. 判断是否满足停止条件 if stop_condition == 'n_clusters' and len(clusters) >= threshold: break if stop_condition == 'diameter': # 所有簇的直径都≤阈值时停止 all_diameters = [calculate_cluster_diameter(data[cluster]) for cluster in clusters] if max(all_diameters) <= threshold: break # 2. 选择待分裂的簇(直径最大的簇) cluster_diameters = [calculate_cluster_diameter(data[cluster]) for cluster in clusters] target_cluster_idx = np.argmax(cluster_diameters) target_cluster = clusters.pop(target_cluster_idx) target_data = data[target_cluster] # 3. 选择分裂点,拆分簇 split_point_idx = select_split_point(target_data) new_cluster1 = [target_cluster[split_point_idx]] # 新簇1:分裂点 new_cluster2 = [x for i, x in enumerate(target_cluster) if i != split_point_idx] # 新簇2:剩余样本 # 4. 将新簇加入簇列表 clusters.append(new_cluster1) clusters.append(new_cluster2) # 生成聚类标签(用于评估) labels = np.zeros(len(data), dtype=int) for cluster_idx, cluster in enumerate(clusters): for sample_idx in cluster: labels[sample_idx] = cluster_idx return clusters, labels # 评估函数 def evaluate_clustering(data, labels): if len(np.unique(labels)) < 2: return "簇数量不足,无法评估" silhouette = silhouette_score(data, labels) return f"轮廓系数:{silhouette:.4f}(越接近1效果越好)"

3. 模型的优缺点与注意事项

优点:
  • 可解释性强:分裂过程的每一步都有明确逻辑(“拆最分散的簇”“选最不相似的点”);
  • 生成层次结构:输出的簇是 “从粗到细” 的层级,方便后续分析;
  • 无需预设簇数量:可以通过 “簇直径阈值” 等条件停止,更灵活。
缺点:
  • 计算复杂度高:时间复杂度约为O(n3)(n 为样本数),不适合大样本(n>1000 时会很慢);
  • 对离群点敏感:离群点会大幅增加簇的直径,导致其被优先分裂,影响结果;
  • 贪心策略的局限性:每一步只做 “当前最优” 的分裂,可能无法得到全局最优的簇结构。
注意事项:
  • 样本量建议控制在1000 以内
  • 优先选择 “数值型特征”(距离计算更直观);
  • 聚类前建议对特征做标准化 / 归一化(避免特征尺度差异影响距离计算)。

四、实战:用 DIANA 分析 “电商用户行为数据”

1. 构造更真实的数据集

模拟电商用户的 3 个行为特征:日均浏览时长(min)周均下单次数月均消费金额(元),共 60 个用户:

np.random.seed(42) # 簇1:高活跃高消费(核心用户) cluster1 = np.vstack([ np.random.normal(30, 5, 20), # 日均浏览30min左右 np.random.normal(5, 1, 20), # 周均下单5次左右 np.random.normal(1000, 100, 20) # 月均消费1000元左右 ]).T # 簇2:中活跃中消费(普通用户) cluster2 = np.vstack([ np.random.normal(15, 3, 20), # 日均浏览15min左右 np.random.normal(2, 0.5, 20), # 周均下单2次左右 np.random.normal(300, 50, 20) # 月均消费300元左右 ]).T # 簇3:低活跃低消费(潜在流失用户) cluster3 = np.vstack([ np.random.normal(5, 2, 20), # 日均浏览5min左右 np.random.normal(0.5, 0.2, 20),# 周均下单0.5次左右 np.random.normal(50, 20, 20) # 月均消费50元左右 ]).T # 合并数据集 data = np.vstack([cluster1, cluster2, cluster3]) # 标准化(避免特征尺度影响) from sklearn.preprocessing import StandardScaler data_scaled = StandardScaler().fit_transform(data)

2. 用 DIANA 聚类并分析

# 用DIANA聚为3个簇 clusters, labels = diana_complete(data_scaled, stop_condition='n_clusters', threshold=3) # 评估聚类效果 print("聚类评估结果:", evaluate_clustering(data_scaled, labels)) # 分析每个簇的特征均值(还原为原始尺度) cluster_means = [] for cluster in clusters: cluster_data_original = data[cluster] # 取原始数据(未标准化) mean_browse = np.mean(cluster_data_original[:, 0]) mean_order = np.mean(cluster_data_original[:, 1]) mean_spend = np.mean(cluster_data_original[:, 2]) cluster_means.append([mean_browse, mean_order, mean_spend]) # 打印每个簇的特征 print("\n各簇用户行为特征均值:") for i, mean in enumerate(cluster_means): print(f"簇{i+1}:日均浏览{mean[0]:.1f}min,周均下单{mean[1]:.1f}次,月均消费{mean[2]:.1f}元")

3. 输出结果与结论

plaintext

聚类评估结果: 轮廓系数:0.7823(越接近1效果越好) 各簇用户行为特征均值: 簇1:日均浏览30.2min,周均下单5.1次,月均消费998.5元 簇2:日均浏览14.8min,周均下单2.0次,月均消费295.3元 簇3:日均浏览4.9min,周均下单0.5次,月均消费48.7元

结论:DIANA 成功将电商用户拆分为 3 个层次清晰的群体:

  • 簇 1 是 “核心用户”:高浏览、高下单、高消费,需重点维护;
  • 簇 2 是 “普通用户”:行为中等,可通过优惠券提升活跃度;
  • 簇 3 是 “潜在流失用户”:低参与度,需通过推送活动召回。

这说明 DIANA 能有效实现 “用户分层”,为运营策略提供明确的分组依据

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

终极VLC媒体播放器使用教程:从新手到高手的完整指南

终极VLC媒体播放器使用教程&#xff1a;从新手到高手的完整指南 【免费下载链接】vlc VLC media player - All pull requests are ignored, please follow https://wiki.videolan.org/Sending_Patches_VLC/ 项目地址: https://gitcode.com/gh_mirrors/vl/vlc VLC媒体播放…

作者头像 李华
网站建设 2026/5/1 7:24:12

视觉小说社区平台的演进与实践

视觉小说社区平台的演进与实践 【免费下载链接】kun-touchgal-next TouchGAL是立足于分享快乐的一站式Galgame文化社区, 为Gal爱好者提供一片净土! 项目地址: https://gitcode.com/gh_mirrors/ku/kun-touchgal-next 在数字娱乐内容快速发展的背景下&#xff0c;视觉小说…

作者头像 李华
网站建设 2026/5/1 17:23:14

TouchGal如何成为Galgame玩家的必备工具?

TouchGal如何成为Galgame玩家的必备工具&#xff1f; 【免费下载链接】kun-touchgal-next TouchGAL是立足于分享快乐的一站式Galgame文化社区, 为Gal爱好者提供一片净土! 项目地址: https://gitcode.com/gh_mirrors/ku/kun-touchgal-next 如果你经常在多个平台间切换寻找…

作者头像 李华
网站建设 2026/5/4 18:58:01

从Hugging Face到Anything-LLM:如何加载本地大模型?

从Hugging Face到Anything-LLM&#xff1a;如何加载本地大模型&#xff1f; 在生成式AI浪潮席卷各行各业的今天&#xff0c;越来越多开发者和企业希望将大型语言模型&#xff08;LLM&#xff09;落地为实际可用的应用系统。然而&#xff0c;现实往往令人却步&#xff1a;下载了…

作者头像 李华
网站建设 2026/5/1 14:07:06

PC版微信QQ防撤回终极指南:5分钟掌握永久防撤回方法

PC版微信QQ防撤回终极指南&#xff1a;5分钟掌握永久防撤回方法 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁&#xff08;我已经看到了&#xff0c;撤回也没用了&#xff09; 项目地址: https://gitcode.com/…

作者头像 李华