Sustie

主页 所有文章 文章检索

数据分析中的association问题及其算法

问题定义

顾客的交易记录可以用一个m×nm \times n的矩阵来表示,如果第ii个顾客购买了第jj个商品,矩阵的第ii行第jj列就为 1,否则为 0。

接下来定义 3 个新概念:association、support 和 confidence。

一个 association 可以用XYX \to Y来表示,其中XXYY都是商品的集合,XY=X \cap Y = \emptyset

一个商品集合的 support 是指交易记录中包含这些商品的交易的个数。一个 association 的 support 是指XYX \cup Y的 support。

一个 association 的 confidence 是指XYX \cup Y的 support 除以XX的 support。

所谓 association 问题就是,给定一个交易记录和两个常数K1K_1K2K_2,希望找到所有的 association,满足其 support K1\ge K_1且 confidence K2\ge K_2

算法框架

总的算法可以分成两步:第一步是找到所有满足 support K1\ge K_1的商品集合,第二步是在第一步的基础上再找出满足条件的 association。

这个过程中最困难的是第一步,因为可以证明第一步是 NP-hard 的。

第二步的算法

假设我们已经找到了 support K1\ge K_1的商品集合的集合S1S_1,那么最终结果S2S_2可以表示为:

S_2 = \{ X \to Y \backslash X | X, Y \in S_1 \land X \subsetneq Y \land \\ \text{confidence}(X \to Y \backslash X) \ge K_2 \}

也就是说,枚举S1S_1中的任意两个商品集合XXYY,如果XYX \subsetneq YXY\XX \to Y \backslash X的 confidence K2\ge K_2,那么就将XY\XX \to Y \backslash X添加到最终结果的集合中。

第一步的算法:Apriori 算法

假设有NN个商品,把我们最终要得到的 support K1\ge K_1的商品集合的集合记作LL(large 的意思)。Apriori 算法的思路是把LL分拆成NN个集合L1,L2,,LNL_1, L_2, \cdots, L_N,其中LiL_iLL中元素个数为ii的商品集合的集合。Apriori 算法会依次寻找L1,L2,L_1, L_2, \cdots,直到LNL_N为止。

要想求出L1L_1是非常容易的,因此接下来只需要解决如何根据LiL_i求出Li+1L_{i+1}。当然我们可以直接用暴力枚举的方法求Li+1L_{i+1},但是这样速度太慢。我们需要考虑如何利用LiL_i更快地求出Li+1L_{i+1}

Apriori 算法的核心是利用了以下性质:如果XYX \subsetneq Y,那么support(X)>support(Y)\text{support}(X) > \text{support}(Y)。根据这个性质,如果XLX \in L,那么其任意子集也必定 L\in L

因此,求Li+1L_{i+1}之前,可以先根据这个必要条件筛选掉一些不可能的商品集合。将筛选后的集合记作Ci+1C_{i+1}(candidate 的意思),则有

C_{i+1} = \{X|\forall a \in X, X\backslash {a} \in L_i \}

上面的公式只是数学描述,实际算法实现可以这么做:首先将LiL_i中的每个商品集合中的商品按照一定顺序排序。然后枚举X,YLiX, Y\in L_i,若X,YX, Y只有最后一个商品不同,其他都相同,则检查XYX \cup Y是否满足上述必要条件,若满足则加入Ci+1C_{i+1}中。

求出Ci+1C_{i+1}之后,还要再查询交易记录,看看Ci+1C_{i+1}中哪些是真的满足 support K1\ge K_1的,就可以求出Li+1L_{i+1}了。

除了上面介绍的 Apriori 算法,还有 FP-Growth 等经典的算法。