复杂结构数据挖掘(二)关联规则挖掘 Association rule mining

作者:nju_spy日期:2025/10/19

你是否曾好奇,为什么超市总把啤酒和尿布摆在一起?这看似随意的陈列背后,藏着数据挖掘领域的经典智慧 —— 关联规则挖掘。在大数据时代,海量交易记录如同未开垦的金矿,而关联规则正是撬开这座金矿的关键工具。想象一下,当你在电商平台浏览商品时,系统推荐的 "买了这个的人还买了...",或是超市根据消费数据优化的货架布局,这些场景背后都离不开关联规则算法的神奇魔力。

从本质上讲,关联规则挖掘要解决的核心问题,是在庞大的交易数据中找出 "X→Y" 这样的隐含关系 —— 例如 "买了面包的人更可能买牛奶"。但面对动辄百万级的商品和交易记录,直接暴力枚举所有可能的商品组合显然不现实。这就像在沙滩上寻找特定形状的贝壳,若没有高效的工具,终将被海量数据淹没。于是,Apriori、FP-growth 等经典算法应运而生,它们如同数据海洋中的导航仪,通过巧妙的剪枝策略和数据结构优化,让我们能在合理时间内挖掘出有价值的规则

从 Apriori 利用 "频繁项集的子集必频繁" 的先验知识进行剪枝,到 DHP 算法引入哈希技术加速候选集筛选;从 FP-growth 通过构建 FP 树实现 "两次扫描数据库即可挖矿" 的高效操作,到 Closed/Maxinal 频繁项集实现的信息精简表示。我们还将登上多层关联规则和多维关联规则的瞭望塔,俯瞰如何在不同概念层级和多维度数据中挖掘隐藏模式,最后还要警惕关联规则可能的 "陷阱"—— 那些看似强大却缺乏实际价值的虚假关联。

目录

1. 关联规则问题的基本定义

2. Apiriori 算法 合并+筛选

2.1 算例

3. DHP 算法 -- 散列表哈希+剪枝

第 1 次扫描:生成 L1 并为 C2 构建散列表

在第 1 次和第 2 次扫描之间:生成剪枝后的 C2

4. FP-growth 频繁模式增长 FP-tree

5. Closed / Maxinal frequent itemset

6. 多层关联规则挖掘 Mining multilevel association rules

6.1 不同的层级策略:

6.2 Redundancy filtering 冗余过滤

7. 多维关联规则挖掘

8. 关联规则 本身可能的问题


1. 关联规则问题的基本定义

给定:

  1. 一个交易数据集 T(例如,所有购物小票的集合)。
  2. 一个物品的集合 I(例如,超市中所有商品的集合)。
  3. 用户自定义的最小支持度阈值 min_sup最小置信度阈值 min_conf

找出:
所有满足以下条件的关联规则 X -> Y(其中 XY 都是物品集 I 的子集,且 X ∩ Y = ∅):

  1. 支持度条件: 规则的支持度 XY一起出现的概率 P(XY) = support(X -> Y)min_sup
    • 目的: 确保规则所描述的模式在数据集中是普遍存在的,不是偶然事件。
  2. 置信度条件: 规则的置信度 P(Y|X) = confidence(X -> Y)min_conf
    • 目的: 确保规则是可靠的,即当前件 X 出现时,后件 Y 也有很高的概率出现。

大规模数据集(如超市数据)难点:物品太多 -> 候选子集太多了;

数支持度和置信度 需要扫描数据库 也耗时。

2. Apiriori 算法 合并+筛选

一个频繁项集的所有子集也一定是频繁的。(加入元素后 出现次数一定非递增)

只能用频繁项集生成更大的频繁项集。

1. 合并生成操作:两个k项集 拼成一个k+1项集(这两个本来只有一个不一样)

2. 筛选:新得到的 k+1项 所有k子项都得频繁。 (新的 k+1 去掉任何一个后都频繁

通过这个必要条件筛选后,再去计算 这个k+1项的支持度和置信度。

第一轮 筛单项,后续先组合+筛,再数一下判断。

2.1 算例

在第二次组合中,虽然 12 24 都在 但因为14不频繁,所以124无法成团。

要124 出现次数 ≥ 2;必要条件 12 24 14 都出现次数 ≥ 2。

ApirioriTid 空间换时间,后续不扫描整个数据库

额外拉一个数据结构:对每笔交易 存频繁k项集 有哪些

3. DHP 算法 -- 散列表哈希+剪枝

Direct Hashing and Pruning 使用散列表直接定位 和 基于散列桶计数进行早期修剪。

Apriori 算法的瓶颈:

由频繁 2-项集(L2)生成候选 3-项集(C3)时,候选集数量会呈组合爆炸式增长。

需要多次扫描整个数据库,并对海量候选集进行支持度计数,耗时太多

加上了散列表构建和剪枝的操作:

第 1 次扫描:生成 L1 并为 C2 构建散列表

  1. 计数:扫描数据库 D,统计每个单项的支持度,生成频繁 1-项集 L1
  2. 为 C2 构建散列表(关键步骤)
    • 散列函数:选择一个散列函数,例如:hash({x, y}) = ((x的序号) * 10 + (y的序号) ) mod n,其中 n 是散列表的大小(桶的数量)。
    • 操作:对于交易 T 中每一个可能的 2-项集 {i, j}(其中 i < j),计算其散列值 h,然后将散列表中h 个桶的计数值加 1。
    • 目的:这个散列表的每个桶的计数,代表了有多少个交易包含了会映射到这个桶的所有 2-项集。“桶支持度”是高于单体支持度的,在后面的筛选中,如果项集映射的桶支持度都低于阈值,单种类项集一定就低于阈值

在第 1 次和第 2 次扫描之间:生成剪枝后的 C2

  1. 生成初始 C2:通过 L1 自连接,生成所有可能的候选 2-项集 C2_candidate
  2. 散列剪枝
    • 对于 C2_candidate 中的每一个候选 2-项集 c,计算对应桶的计数。
    • 修剪规则:如果桶的计数 < min_sup,那么意味着即使把所有映射到这个桶的项集都算上,它们的总支持度也达不到最小支持度。因此,这个桶里的任何一个具体的候选集 c绝对不可能是频繁的。 就把这个候选 pass掉。

后续流程类似:

  1. 扫描数据库,统计剪枝后的 Ck 的支持度,生成频繁集 Lk
  2. 在扫描的同时,可以为 C{k+1} 构建散列表(并应用事务裁剪:只处理项数 >= k+1 的交易)。
  3. 利用新构建的散列表对下一步生成的 C{k+1} 进行剪枝

4. FP-growth 频繁模式增长 FP-tree

-- 之前方法的两个问题:

在CPU上处理比较快,但是**扫描数据库(验证这个组合符不符合)**太耗时了;

上两种方法 generation-and-test 的范式,丢失了很多生成信息

-- 能否只扫描数据库两次,就将整个数据库压缩成一棵高度浓缩的数据结构 FP-tree,然后在这棵树上进行“挖矿”,完全避免产生候选集?

先根据 单项的 frequent 信息,对每个T 交易的每样物品进行排序,并删掉不频繁的单项。

如何表征 商品出现在一个购物车里? 建树的时候串起来

由于排序过 实现了共享前缀自底向上拎起来 就是这一组的出现次数。

建树过程有点像字典树:

对单项:数 + 留频繁 + 排序

每个交易小票 transaction:根连着首项,接着后一个,如果没有就开一个新后继。节点计数+1。

对同一个字母 前后用链串起来方便后续检索。

如何产生频繁项集:

1. 先选一个开始的项(后面算带这个项的 所有频繁的)

2. 通过项 X节点链,收集所有包含 X 的前缀路径。

每一条从根节点到 X 的父节点的路径,就是 X 的一个条件模式基

如果路径 A->B->C 指向 X:2,那么这条条件模式基就是 {A, B, C}:2

要找带 m 的串,沿着m的链,往上找前缀:

把前缀统计合并,带 m 的频繁集,只需对前缀进行 0-1 选取。

优化技巧:从中间分治 先做上面的,再把上面作为一个整体节点。

合并:集合乘法;前面选几个,后面选几个

例2:min_sup=2

5. Closed / Maxinal frequent itemset

一个 N-频繁项集的所有 2^N - 1 个子集 全都是频繁的。

我们不需要把 它的这些子集全都挖掘出来,这个 N-频繁项集 已经包含了全部的信息

精简表示 -> 最少保存多少信息 就可以知道全部的信息呢?

Closed:加任何元素之后,支持度都会下降

Maxinal:再塞元素就不频繁了。(包含于Closed)

6. 多层关联规则挖掘 Mining multilevel association rules

Concept Hierarchies(概念层次结构) 进行规则泛化的尺度。(不同层次商品)

啤酒与尿布显著,但某种啤酒和某种尿布 不一定显著。

小朋友喜欢吃KFC 泛化到人喜欢吃饭 还有没有意义。

不是每层分开算 利用不同层次之间关系。

6.1 不同的层级策略:

方法类别核心判断依据优势劣势
逐层独立不考虑父节点是否频繁,所有节点都检查不遗漏关联检查大量无用(不频繁、不重要)项
基于k项集的跨层过滤父k项集频繁,才检查子k项集只关注频繁项的子项,减少无效检查可能漏掉有价值但父项集不频繁的模式
基于单个项的跨层过滤父节点(单个项)频繁,才检查子节点平衡 “全检查” 和 “只查频繁父项集子项”可能漏掉父节点不频繁、但自身(子项)在低支持度下频繁的关联
受控的基于单个项的跨层过滤父项满足 “层级传递阈值”(非严格最小支持度),则子项可被检查放宽限制,让更多潜在项有被检查的可能阈值设置难度大,不好把控

6.2 Redundancy filtering 冗余过滤

有意义的规则(去除冗余 有不一样)

祖先(规则层面):如果规则R1可以通过将规则R2中的项替换为它们在概念层次结构中的祖先项而得到,那么规则R1就是规则R2的祖先。

如果一条规则的支持度和置信度与其祖先规则的 “预期” 支持度和置信度接近,那么这条规则可以被认为是冗余的。

例如:若 IBM computer -> HP printer 与 computer -> HP printer 按比例缩放

那么是不是 IBM电脑 对HP打印机没有影响,记录这条规则就是冗余的。

如果发现 买 IBM电脑的人 相较于整体买电脑的人,买HP打印机远远少,这个额外信息就是有作用的。

7. 多维关联规则挖掘

单维度: IBM 电脑 -> HP 打印机

多维度: IBM 电脑 + 20-24岁 -> HP 打印机 (前面多变量影响)

多维关联规则挖掘寻找的是频繁谓词集(前面k个指标组合)

如果有很多购物记录都同时满足P1^P2^P3(即“年龄20-30岁、收入超5000元、买了笔记本电脑”),那么谓词集{P,P2,P3}就是一个频繁谓词集。

数值型属性动态离散化:分箱 + 找频繁 + 聚类合并

8. 关联规则 本身可能的问题

例:60%买游戏 75%买光盘 40%都买 66%买游戏的买了光盘,

那么 买游戏 -> 买光盘 (40%,66%)达到了支持度和置信度。(按之前 这符合关联规则)

但是实际上 66% < 75% 买游戏反而对买光盘产生了负面作用

置信度降低了,但仍然高于阈值。

Criticism: Strong association rules may not be interesting 符合要求 但不有趣(没用)

定义提升率:条件概率 除以 本来概率,和1比 是促进还是抑制。


复杂结构数据挖掘(二)关联规则挖掘 Association rule mining》 是转载文章,点击查看原文


相关推荐


程序员必备!5 款免费又好用的数据库管理工具推荐
追逐时光者2025/10/18

前言 在数据驱动的时代,数据库管理工具对于程序员而言如同瑞士军刀般不可或缺。它们不仅能够帮助我们高效地管理数据库,还能提升数据处理的准确性和速度。今天大姚给大家分享 5 款免费且实用的数据库管理工具(排名不分先后,欢迎文末留下你常用的数据库管理工具),希望可以帮助到有需要的同学。 DataGrip DataGrip 是 JetBrains 推出的一款跨平台(在 Windows、macOS 和 Linux 上提供一致的体验)数据库 IDE,专为 SQL 开发与数据库管理而打造。它集智能代码补全、A


kotlin中MutableStateFlow和MutableSharedFlow的区别是什么?
AsiaLYF2025/10/16

在 Kotlin 的协程库(kotlinx.coroutines.flow)中,MutableStateFlow 和 MutableSharedFlow 都是用于构建响应式数据流的可变(Mutable)热流(Hot Flow),但它们的设计目标和行为特性有显著区别。以下是它们的核心对比: 1. 核心区别总结 特性MutableStateFlowMutableSharedFlow数据保留始终保存最新一个值(必须有初始值)不保留值(默认),但可配置缓冲区保留历史值订阅时机新订阅者立即收到当前最新


组合为什么优于继承:从工程实践到数学本质
canonical_entropy2025/10/15

在面向对象设计的殿堂里,"组合优于继承"(Composition over Inheritance)是一条近乎金科玉律的原则。每一位有经验的开发者都会告诫新手:优先使用组合,谨慎使用继承。但这背后的原因究竟是什么?仅仅是因为组合更加灵活吗?答案远不止于此。这种设计偏好的背后,实际上隐藏着深刻的数学原理,它关乎系统结构的稳定性、可预测性和长期可维护性。 第一部分:工程实践的智慧结晶 在日常编程实践中,我们对"组合优于继承"有着直观而实用的理解。 继承的"白盒"困境 继承建立了一种"is-a"(是一


这份超全JavaScript函数指南让你从小白变大神
良山有风来2025/10/14

你是不是曾经看着JavaScript里各种函数写法一头雾水?是不是经常被作用域搞得晕头转向?别担心,今天这篇文章就是要帮你彻底搞懂JavaScript函数! 读完本文,你将收获: 函数的各种写法和使用场景 参数传递的底层逻辑 作用域和闭包的彻底理解 箭头函数的正确使用姿势 准备好了吗?让我们开始这场函数探险之旅! 函数基础:从“Hello World”开始 先来看最基础的函数声明方式: // 最传统的函数声明 function sayHello(name) { return "Hello


武装你的Python“工具箱”:盘点10个你必须熟练掌握的核心方法
烛阴2025/10/12

一、字符串方法 字符串处理是我们日常编程中最高频的操作之一。 .strip() - 去除首尾空白 示例: user_input = " admin \n" cleaned_input = user_input.strip() print(f"清理前: '{user_input}', 清理后: '{cleaned_input}'") # 输出: #清理前: ' admin #', 清理后: 'admin' .split() - 字符串切割 示例: csv_line =


我用亲身经历告诉你,为什么程序员千万别不把英语当回事
oioihoii2025/10/10

年轻人,如果你现在觉得写代码只需要认识 if/else 和 for 循环里的那几个英文单词就够了,那你简直像极了十年前的我。而今天的我,多想回到过去,给那个骄傲自满的自己一记响亮的耳光。 我不是以成功者的姿态来教导你,而是以一个踩过坑、吃过亏、肠子都悔青了的过来人身份,跟你聊聊我最后悔的一件事——没有早点学好英语。 一、工作里吃的哑巴亏,都是我当年脑子进的水 1. “啃”二手资料的酸楚 还记得那次,团队要引入一个热门的新框架。我兴冲冲地找了几篇中文博客,照猫画虎地搞了起来。结果,掉进了一个坑里,


Seata分布式事务框架详解与项目实战
IT橘子皮2025/10/9

一、Seata核心架构与原理 Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,旨在为微服务架构提供高性能、易用性的分布式事务支持。其核心设计理念是"化繁为简",通过封装传统分布式事务模式的复杂性,降低分布式一致性问题的解决门槛。 ​核心组件​: ​TC(Transaction Coordinator)​​:事务协调者,维护全局事务和分支事务的状态,负责协调全局事务提交或回滚 ​TM(


【鸿蒙生态共建】一文说清复杂类型数据的非预期输入转换与兜底-《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
俩毛豆2025/10/7

在客户端开发中,你是否曾遇到过这样的困扰:一次看似寻常的网络数据解析,却导致了出人意料的崩溃;一个本该正常的文件读取操作,却返回了难以理解的数据错误。这些问题的根源,往往指向同一环节——数据类型转换。当应用面对网络传输、文件I/O等不可控的数据源时,如何稳健、准确地进行数据解析与转换,就成为保障应用稳定性的第一道防线。 本篇内容是《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》这本书第四章内容的延续,是咱这本书读者的福利,在本篇内容中以模拟多种数据输入,向复杂类型(类、数


Spring Cloud之负载均衡之LoadBalance
新绿MEHO2025/10/6

目录 负载均衡 问题 步骤 现象  什么是负载均衡? 负载均衡的一些实现 服务端负载均衡 客户端负载均衡 使用Spring Cloud LoadBalance实现负载均衡 负载均衡策略 ​编辑 ​编辑LoadBalancer原理 服务部署 准备环境和数据 服务构建打包 启动服务 上传Jar包到云服务器 启动服务 远程调用访问  负载均衡 问题 上面是我们之前的代码,是根据应用名称获取了服务实例列表,并从列表中选择了一个服务实例。 那如果


Qwen3 Omni 的“全模态”,到底和多模态有啥不一样?
飞哥数智谈2025/10/5

前一阵阿里云栖大会,其中有个发布内容是全模态大模型 Qwen3-Omni。 说实话,这是我第一次真正地审视“全模态大模型”这个概念,因为之前 Qwen2.5-Omni 发布的时候,有了解过,但不多。 简介 先从概念上简单介绍下什么是“全模态大模型”。 “Qwen3-Omni是新一代原生全模态大模型,能够无缝处理文本、图像、音频和视频等多种输入形式,并通过实时流式响应同时生成文本与自然语音输出。” 多模态大模型 vs 全模态大模型 接下来,为了更好地理解,我们与“多模态大模型”做个对比。 相同点是

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0