关联规则挖掘的Apriori算法原理与实现步骤
题目描述
我们如何在大量的交易数据(例如超市的购物小票)中,自动发现诸如“购买啤酒的人经常同时购买尿布”这类有意义的商品组合规律?这就是关联规则挖掘的核心问题。Apriori算法是解决该问题最经典、最广为人知的算法。题目要求我们深入理解Apriori算法的核心原理、逐层搜索的策略,以及其完整的实现步骤。
解题过程
第一步:理解问题与核心概念
关联规则挖掘的目标是从交易数据库中找出形如 \(X \rightarrow Y\) 的规则,表示“如果项集 \(X\) 出现,则项集 \(Y\) 也很可能出现”。
需要定义两个关键度量标准:
- 支持度 (Support):衡量规则的重要性(普遍性)。
\[ \text{支持度}(X \rightarrow Y) = \frac{\text{同时包含 } X \text{ 和 } Y \text{ 的交易数}}{\text{总交易数}} \]
它反映了 $ X $ 和 $ Y $ 同时出现的频率。
- 置信度 (Confidence):衡量规则的可靠性。
\[ \text{置信度}(X \rightarrow Y) = \frac{\text{同时包含 } X \text{ 和 } Y \text{ 的交易数}}{\text{包含 } X \text{ 的交易数}} = \frac{\text{支持度}(X \cup Y)}{\text{支持度}(X)} \]
它反映了在 $ X $ 出现的前提下,$ Y $ 也出现的条件概率。
我们的目标是找到所有满足 最小支持度阈值 和 最小置信度阈值 的强关联规则。
第二步:认识搜索空间的挑战与Apriori的先验原理
假设有 \(N\) 种不同的商品,那么所有可能的商品组合(称为项集)数量是 \(2^N - 1\)。对于大规模数据(例如 \(N=10,000\)),这是天文数字,无法暴力枚举。
Apriori算法的核心洞察是一个先验性质:
如果一个项集是频繁的,那么它的所有子集也一定是频繁的。
反之,如果一个项集是非频繁的,那么包含它的所有超集也一定是非频繁的。
逻辑推导:
- 设项集 \(A\) 的支持度为 \(s(A)\)。
- 如果 \(B\) 是 \(A\) 的超集(即 \(A \subset B\)),那么任何包含 \(B\) 的交易必然也包含 \(A\)。因此,支持度 \(s(B) \le s(A)\)。
- 如果我们设定最小支持度阈值为
min_sup,且 \(s(A) < \text{min\_sup}\)(即 \(A\) 是非频繁项集),则必然有 \(s(B) < \text{min\_sup}\)。所以 \(B\) 也是非频繁的。
这个性质是反单调的:一个项集“非频繁”的性质,会传递给它的所有超集。这允许我们在搜索时进行大量剪枝。
第三步:Apriori算法的逐层迭代过程
算法采用一种由下至上、逐层搜索的迭代方法,每一层 \(k\) 寻找所有大小为 \(k\) 的频繁项集(记为 \(L_k\))。
过程详解:
-
初始化 (k=1):
- 扫描整个数据库,计算每个单个商品(1-项集)的支持度。
- 将支持度不低于
min_sup的1-项集保留下来,形成频繁1-项集集合 \(L_1\)。
-
迭代过程 (从 k=2 开始):
A. 连接步 (Candidate Generation):- 目标:基于上一层的频繁项集 \(L_{k-1}\) ,生成候选的 \(k\)-项集集合 \(C_k\)。
- 方法:将 \(L_{k-1}\) 中的两个项集连接,条件是它们的前 \(k-2\) 个项相同。
\[ \text{对于 } l_1, l_2 \in L_{k-1},如果\ (l_1[1]=l_2[1]) \land ... \land (l_1[k-2]=l_2[k-2]) \land (l_1[k-1] < l_2[k-1]),则生成候选\ l_1 \cup l_2。 \]
*例如, $ L_2 $ 中有 {A, B}, {A, C}, {B, C}。连接 {A, B} 和 {A, C}(前1项相同,且B<C),生成候选3-项集 {A, B, C}。*
B. **剪枝步 (Pruning)**:
- 利用Apriori原理进行剪枝:检查 $ C_k $ 中每个候选 $ k $-项集的 **所有大小为 $ k-1 $ 的子集** 是否都在 $ L_{k-1} $ 中。
- 如果存在某个子集不在 $ L_{k-1} $ 中(即非频繁),则该候选 $ k $-项集绝不可能是频繁的,将其从 $ C_k $ 中删除。
*例如,在上面的 {A, B, C} 中,检查其子集 {A, B}, {A, C}, {B, C}。如果 {B, C} 不在 $ L_2 $ 中,则丢弃 {A, B, C}。*
C. **计数与筛选步 (Support Counting and Filtering)**:
- 扫描数据库,计算 $ C_k $ 中所有剩余候选集的实际支持度。
- 将支持度不低于 `min_sup` 的候选集保留,形成频繁 $ k $-项集集合 $ L_k $。
- 终止条件:
- 当无法生成新的候选集(即 \(C_{k+1}\) 为空)或 \(L_k\) 为空时,算法终止。
- 此时,我们得到了所有满足最小支持度要求的频繁项集集合 \(L = L_1 \cup L_2 \cup ... \cup L_k\)。
第四步:从频繁项集生成关联规则
在获得所有频繁项集后,我们从中生成强关联规则。
对于每一个频繁项集 \(l\) (至少包含2个项):
- 生成 \(l\) 的所有非空真子集作为规则的前件 \(X\),则后件 \(Y = l \setminus X\)。
例如,对于频繁项集 {A, B, C},可能的规则前件有 {A}, {B}, {C}, {A, B}, {A, C}, {B, C}。 - 对每一个这样生成的规则候选 \(X \rightarrow Y\),计算其置信度:
\[ \text{置信度} = \frac{\text{支持度}(l)}{\text{支持度}(X)} \]
由于 $ l $ 和 $ X $ 都是频繁项集,它们的支持度已知。
- 如果该规则的置信度不低于预设的 最小置信度阈值 (
min_conf),则保留它为强关联规则。
优化:与项集挖掘类似,规则生成也可以利用置信度的反单调性进行剪枝:如果规则 \(X \rightarrow Y\) 不满足最小置信度,那么对于 \(X\) 的任何子集 \(X' \subset X\),规则 \(X' \rightarrow (Y \cup (X \setminus X‘))\) 的置信度会更低,也不可能是强规则。
总结
Apriori算法通过其核心的先验剪枝原理,将指数级的搜索问题转化为可控的逐层迭代过程。它清晰地区分了 频繁项集挖掘 和 规则生成 两个阶段,是理解关联规则挖掘的基石。尽管其需要多次扫描数据库(效率上可能不如后续的FP-Growth等算法),但其思想直观深刻,至今仍在许多数据挖掘场景中被广泛使用和借鉴。