HAWQ + MADlib 玩转数据挖掘之(七) —— 关联规则方法之 Apriori 算法

本文介绍Apriori算法原理及应用,涵盖关联规则挖掘的基本概念、Apriori算法的工作流程和Madlib中的Apriori函数使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、关联规则简介

二、关联规则的基本概念

1. 项目与项集

2. 事务

3. 关联规则

4. 项集的频数(Count)

5. 支持度(Support)

6. 关联规则的支持度

7. 关联规则的置信度(Confidence)

8. 关联规则的提升度(Lift)

9. 关联规则的确信度(Conviction)

10. 最小支持度与最小置信度

11. 频繁项集

12. 强关联规则

三、Apriori 算法

1. Apriori 算法基本思想

2. Apriori 算法步骤

四、MADlib 中的 Apriori 算法函数

1. 语法

2. 参数说明

五、Apriori 算法应用示例

1. 创建输入数据集

2. 调用 madlib.assoc_rules 函数生成关联规则

3. 限制生成关联规则的项集大小为 2

4. 按需过滤关联规则

5. 分析关联规则

参考:


一、关联规则简介

        关联规则挖掘的目标是发现数据项集之间的关联关系,是数据挖据中一个重要的课题。关联规则最初是针对购物篮分析(Market Basket Analysis)问题提出的。假设超市经理想更多地了解顾客的购物习惯,特别是想知道,哪些商品顾客可能会在一次购物时同时购买?为回答该问题,可以对商店的顾客购买记录进行购物篮分析。该过程通过发现顾客放入“购物篮”中的不同商品之间的关联,分析顾客的购物习惯。这种关联的发现可以帮助零售商了解哪些商品频繁地被顾客同时购买,从而帮助他们开发更好的营销策略。

        为了对顾客的购物篮进行分析,1993年,Agrawal 等首先提出关联规则的概念,同时给出了相应的挖掘算法 AIS,但是性能较差。1994年,又提出了著名的 Apriori 算法,至今仍然作为关联规则挖掘的经典算法被广泛讨论。

        一个使用关联规则的经典购物篮分析案例是“啤酒与尿布”规则。根据对超市的顾客购买行为的数据挖掘发现,男顾客经常一起购买啤酒和尿布,于是经理决定将啤酒与尿布放置在一起,让顾客很容易在货架上看到,从而使销售额大幅度增长。关联规则挖掘除了应用于购物篮分析,在其他领域也得到了广泛应用,包括生物工程、互联网分析、电信和保险业的错误校验等。

        Apriori 数据挖掘算法使用事务数据,每个事务事件都具有唯一标识,事务由一组项目(或项集)组成。购买行为被认为是一个布尔值(买或不买),这种实现不考虑每个项目的购买数量。MADlib 的关联规则函数假设数据存储在事务 ID 与项目两列中。具有多个项的事务将扩展为多行,每行一项目,如:

    trans_id | product
    ---------+---------
           1 | 1
           1 | 2
           1 | 3
           1 | 4
           2 | 3
           2 | 4
           2 | 5
           3 | 1
           3 | 4
           3 | 6
    ...

二、关联规则的基本概念

        先了解一下关联规则挖掘中涉及的几个基本概念。

1. 项目与项集

        数据库中不可分割的最小单位信息,称为项目,用符号 i 表示,项目的集合称为项集。设集合 I={i1,i2,...ik} 是项集,I 中项目的个数为 k,则集合 I 称为 k-项集。例如,集合{啤酒,尿布,牛奶}是一个 3-项集。

2. 事务

        设 I={i1,i2,...ik} 是由数据库中所有项目构成的集合,一次处理所含项目的集合用 T 表示,T={t1,t2,...tn},每个 ti 包含的项集都是I的子集。例如,如果顾客在商场里同一次购买多种商品,这些购物信息在数据库中有一个唯一的标识,用以表示这些商品是同一顾客同一次购买的。称该用户的本次购物活动对应一个事务。

3. 关联规则

        关联规则是形如 X=>Y 的蕴含式,意思是“如果 X 则 Y”,其中 X、Y 都是 I 的子集,且 X 与 Y 交集为空。X、Y 分别称为规则的前提和结果,或者规则的左、右。关联规则反映 X 中的项目出现时,Y 中的项目也跟着出现的规律。

4. 项集的频数(Count)

        对于任何给定的项集 X,包含 X 的事务数,称为 X 的频数。

5. 支持度(Support)

        包含项集 X 的事务数与总事务数之比,称为 X 的支持度,记为:

6. 关联规则的支持度

        关联规则的支持度是事务集中同时包含 X 和 Y 的事务数与所有事务数之比,其实也就是两个项集 {X Y} 出现在事务中的频率,记为:

7. 关联规则的置信度(Confidence)

        关联规则的置信度是事务集中包含 X 和 Y 的事务数与所有包含 X 的事务数之比,也就是当项集 X 出现时,项集 Y 同时出现的概率,记为:

8. 关联规则的提升度(Lift)

        关联规则的提升度定义为:

        提升度表示含有 X 的条件下,同时含有 Y 的概率,与不含 X 的条件下却含有 Y 的概率之比。这个值越大,越表明 X 和 Y 有较强的关联度。

9. 关联规则的确信度(Conviction)

        关联规则的确信度定义为:

        表示 X 出现而 Y 不出现的概率,也就是规则预测错误的概率。确信度也用来衡量 X 和 Y 的独立性,这个值越大,X、Y 越关联。

10. 最小支持度与最小置信度

        通常用户为了达到一定的要求,需要指定规则必须满足的支持度和置信度阈值,当 support(X=>Y)、confidence(X=>Y) 分别大于等于各自的阈值时,认为 X=>Y 是有趣的,此两个值称为最小支持度阈值(min_sup)和最小置信度阈值(min_conf)。其中,min_sup 描述了关联规则的最低重要程度,min_conf 规定了关联规则必须满足的最低可靠性。

11. 频繁项集

        设 U={u1,u2,...,un} 为项目的集合,且 U⊆I,U≠∅,对于给定的最小支持度 min_sup,如果项集 U 的支持度 support(U)>=min_sup,则称 U 为频繁项集,否则 U 为非频繁项集。

12. 强关联规则

        support(X=>Y)>=min_sup 且 confidence(X=>Y)>=min_conf,称关联规则 X=>Y 为强关联规则,否则称 X=>Y 为弱关联规则。

        下面用一个简单的例子来说明这些定义。假设表1 是顾客购买记录的数据库 D,包含 6 个事务。项集 I={网球拍,网球,运动鞋,羽毛球}。考虑关联规则:网球拍=>网球,事务 1、2、3、4、6 包含网球拍,事务 1、2、6 同时包含网球拍和网球,支持度 support=3/6,置信度 confidence=3/5,提升度 lift=(3/6)/((5/6) * (4/6))=9/10,确信度 conviction=(1-4/6)/(1-3/5)=5/6。若给定最小支持度 α=0.5,最小置信度 β=0.5,关联规则网球拍=>网球是有趣的,认为购买网球拍和购买网球之间存在强关联规则。但是,由于提升度 Lift 小于 1,就是说是否够购买网球,与有没有购买网球拍关联性很小。当提升度 Lift(X=>Y)>1 时,则规则“X=>Y”是有效的强关联规则,否则,规则“X=>Y”是无效的强关联规则,特别地,如果 Lift(X=>Y)=1,则表示 X 与 Y 相互独立。因此规则网球拍=>网球是无效的强关联规则。

TID

网球拍

网球

运动鞋

羽毛球

1

1

1

1

0

2

1

1

0

0

3

1

0

0

0

4

1

0

1

0

5

0

1

1

1

6

1

1

0

0

表1

三、Apriori 算法

1. Apriori 算法基本思想

        关联规则的挖掘分为两步:(1)找出所有频繁项集;(2)由频繁项集产生强关联规则。而其总体性能由第一步决定。在搜索频繁项集时,最简单、最基本的算法就是 Apriori 算法。算法的名字基于这样一个事实:算法使用频繁项集的先验知识。Apriori 使用一种被称作逐层搜索的迭代方法,k 项集用于搜索(k+1)项集。首先,通过扫描数据库,积累每个项目的计数,并收集满足最小支持度的项目,找出频繁 1 项集的集合,该集合记作 L1。然后,L1 用于找频繁 2 项集的集合 L2,L2 用于找 L3,如此下去,直到不能再找到频繁 k 项集。找每个 Lk 需要一次数据库全扫描。

        Apriori 核心算法思想简要描述如下:该算法中有两个关键步骤为连接和剪枝。

(1)连接

        为找出 Lk(频繁 k 项集),通过 Lk-1 与自身连接,产生候选 k 项集,该候选项集记作 Ck;其中 Lk-1 的元素是可连接的。

(2)剪枝

        Ck 是 Lk 的超集,即它的成员可以是也可以不是频繁的,但所有的频繁项集都包含在 Ck 中。扫描数据库,确定 Ck 中每一个候选项的计数,从而确定 Lk(计数值不小于最小支持度计数的所有候选是频繁的,从而属于 Lk)。然而,Ck 可能很大,这样所涉及的计算量就很大。为了压缩 Ck,使用 Apriori 性质:任一频繁项集的所有非空子集也必须是频繁的,反之,如果某个候选的非空子集不是频繁的,那么该候选肯定不是频繁的,从而可以将其从 CK 中删除。例如,如果 {A,B,C} 是一个 3 项的频繁项集,则其子集 {A,B}、{B,C}、{A,C} 也一定是 2 项的频繁项集。剪枝事先对候选集进行过滤,以减少访问外存的次数,而这种子集测试本身可以使用所有频繁项集的散列树快速完成。

2. Apriori 算法步骤

        假设给定最小支持度和最小置信度,Apriori 算法的主要步骤如下:

  1. 扫描全部数据,产生候选 1-项集的集合 C1;
  2. 根据最小支持度,由候选 1-项集集合 C1 产生频繁 1-项集的集合 L1;
  3. 对 k>1,重复执行步骤 4、5、6;
  4. 由 Lk 执行连接和剪枝操作,产生候选 (k+1)-项集的集合 Ck+1;
  5. 根据最小支持度,由候选 (k+1)-项集的集合 Ck+1,产生频繁 (k+1)-项集的集合 Lk+1;
  6. 若 L≠∅,则 k=k+1,跳往步骤 4;否则跳往步骤 7;
  7. 设产生的频繁项集为 A,A 的所有真子集为 B,根据最小置信度,产生 B=>(A-B) 的强关联规则,结束。

四、MADlib 中的 Apriori 算法函数

        MADlib 的 assoc_rules 函数生成所有满足给定最小支持度和最小置信度的关联规则。

1. 语法

assoc_rules( support,
             confidence,
             tid_col,
             item_col,
             input_table,
             output_schema,
             verbose,
             max_itemset_size
           );

2. 参数说明

        support:最小支持度
        confidence:最小置信度
        tid_col:事务 ID 列名
        item_col:项目对应的列名。
        input_table:包含输入数据的表名。输入表的结构为:

{TABLE|VIEW} input_table (
    trans_id INTEGER,
    product TEXT
)

        该算法将产品名称映射到从 1 开始的连续的整型事务 ID 上。如果输入数据本身已经结构化为这种形式,则事务 ID 保持不变。

        output_schema:存储最终结果的模式名称,调用函数前,模式必须已创建。如果此参数为 NULL,则输出到当前模式。结果中包含规则、支持度、频数、置信度、提升度和确信度,存储在输出模式中的 assoc_rules 表中。该表具有以下列:

   Column   |       Type       
------------+------------------
 ruleid     | integer           
 pre        | text[]            
 post       | text[]            
 count      | integer           
 support    | double precision  
 confidence | double precision  
 lift       | double precision  
 conviction | double precision

        在 HAWQ 中,assoc_rules 表通过 ruleid 列分布存储。pre 和 post 列分别是相应关联规则的左右项集。count、support、confidence、lift 和 conviction 列分别对应关联规则的频数、支持度、置信度、提升度和确信度。

        verbose:BOOLEAN 类型,缺省值为 false,是否详细打印算法过程中每次迭代的结果。
        max_itemset_size:INTEGER 类型,参数值必须大于等于 2,指定用于产生关联规则的频繁项集的大小,缺省值是产生全部项集。当项集太大时,可用此参数限制数据集的大小,以减少运行时长。

五、Apriori 算法应用示例

1. 创建输入数据集

drop table if exists test_data;
create table test_data (
    trans_id int,
    product text
);
insert into test_data values (1, 'beer');
insert into test_data values (1, 'diapers');
insert into test_data values (1, 'chips');
insert into test_data values (2, 'beer');
insert into test_data values (2, 'diapers');
insert into test_data values (3, 'beer');
insert into test_data values (3, 'diapers');
insert into test_data values (4, 'beer');
insert into test_data values (4, 'chips');
insert into test_data values (5, 'beer');
insert into test_data values (6, 'beer');
insert into test_data values (6, 'diapers');
insert into test_data values (6, 'chips');
insert into test_data values (7, 'beer');
insert into test_data values (7, 'diapers');

2. 调用 madlib.assoc_rules 函数生成关联规则

        设置最小支持度 min(support) = 0.25,最小置信度 min(confidence) = 0.5。输出模式设置为 NULL,输出到当前模式。verbose 设置为 TRUE,这样就能观察和验证函数执行的过程。

select * from madlib.assoc_rules( .25,            -- support
                                  .5,             -- confidence
                                  'trans_id',     -- transaction id col
                                  'product',      -- product col
                                  'test_data',    -- input data
                                  null,           -- output schema
                                  true            -- verbose output
                                );

        输出如下:

INFO:  finished checking parameters
CONTEXT:  PL/Python function "assoc_rules"
INFO:  finished removing duplicates
CONTEXT:  PL/Python function "assoc_rules"
INFO:  finished encoding items
CONTEXT:  PL/Python function "assoc_rules"
INFO:  finished encoding input table: 4.55814695358
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Beginning iteration #1
CONTEXT:  PL/Python function "assoc_rules"
INFO:  3 Frequent itemsets found in this iteration
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Completed iteration # 1. Time: 0.756361961365
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Beginning iteration # 2
CONTEXT:  PL/Python function "assoc_rules"
INFO:  time of preparing data: 0.784854888916
CONTEXT:  PL/Python function "assoc_rules"
INFO:  3 Frequent itemsets found in this iteration
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Completed iteration # 2. Time: 1.89147591591
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Beginning iteration # 3
CONTEXT:  PL/Python function "assoc_rules"
INFO:  time of preparing data: 0.577459096909
CONTEXT:  PL/Python function "assoc_rules"
INFO:  1 Frequent itemsets found in this iteration
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Completed iteration # 3. Time: 1.32646298409
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Beginning iteration # 4
CONTEXT:  PL/Python function "assoc_rules"
INFO:  time of preparing data: 0.31945681572
CONTEXT:  PL/Python function "assoc_rules"
INFO:  0 Frequent itemsets found in this iteration
CONTEXT:  PL/Python function "assoc_rules"
INFO:  Completed iteration # 4. Time: 0.751129865646
CONTEXT:  PL/Python function "assoc_rules"
INFO:  begin to generate the final rules
CONTEXT:  PL/Python function "assoc_rules"
INFO:  7 Total association rules found. Time: 1.1944539547
CONTEXT:  PL/Python function "assoc_rules"
 output_schema | output_table | total_rules |   total_time    
---------------+--------------+-------------+-----------------
 public        | assoc_rules  |           7 | 00:00:10.566625
(1 row)

        madlib.assoc_rule 函数产生频繁项集及关联规则的过程如下:

(1)验证参数、去除重复数据、输入数据编码(生成从 1 开始的连续的事务 ID,本例不需要)

(2)首次迭代,生成所有支持度大于等于 0.25 的 1 阶项集作为初始项集,如表2 所示。

项集

频数

支持度

beer

7

7/7

diapers

5

5/7

chips

3

3/7

表2

        因为三个 1 阶项集的支持度都大于 0.25,所以初始项集包含所有三个项集。

(3)最大阶数为 3,因此开始第二次迭代。第二次迭代结果的频繁项集如表3 所示。

项集

频数

支持度

beer, diapers

5

5/7

beer, chips

3

3/7

diapers,chips

2

2/7

表3

        因为三个 2 阶项集的支持度都大于 0.25,所以本次迭代结果的频繁项集包含所有三个项集。

(4)第三次迭代,得到的频繁项集如表4 所示。

项集

频数

支持度

beer, diapers, chips

2

2/7

表4

        因为唯一一个 3 阶项集的支持度大于 0.25,所以本次迭代结果的频繁项集包含一个项集。

(5)第四次迭代,因为阶数为 3,本次迭代的结果为空集。

(6)产生关联规则,置信度大于等于 0.5 的关联规则如表5 中粗体行所示。

前提

结果

支持度

置信度

beer

diapers

5/7=0.71428571

(5/7)/(7/7)= 0.71428571

diapers

beer

5/7=0.71428571

(5/7)/(5/7)=1

beer

chips

3/7=0.42857143

(3/7)/(7/7)= 0.42857143

chips

beer

3/7=0.42857142

(3/7)/(3/7)=1

diapers

chips

2/7=0.28571429

(2/7)/(5/7)=0.4

chips

diapers

2/7=0.28571429

(2/7)/(3/7)=0.66666667

beer

diapers, chips

2/7=0.28571429

(2/7)/(7/7)= 0.28571429

beer,diapers

chips

2/7=0.28571429

(2/7)/(5/7)=0.4

beer,chips

diapers

2/7=0.28571429

(2/7)/(3/7)= 0.66666667

diapers

beer,chips

2/7=0.28571429

(2/7)/(5/7)=0.4

diapers,chips

beer

2/7=0.28571429

(2/7)/(2/7)=1

chips

beer, diapers

2/7=0.28571429

(2/7)/(3/7)= 0.66666667

表5

        关联规则存储在 assoc_rules 表中:

select ruleid,     
       pre,            
       post,            
       count,           
       round(support::numeric,8) support,  
       round(confidence::numeric,8) confidence,
       round(lift::numeric,8) lift,
       round(conviction::numeric,8) conviction
  from assoc_rules 
 order by support desc, confidence desc;

        查询结果与表5 所反映的相同:

 ruleid |       pre       |      post      | count |  support   | confidence |    lift    | conviction 
--------+-----------------+----------------+-------+------------+------------+------------+------------
      2 | {diapers}       | {beer}         |     5 | 0.71428571 | 1.00000000 | 1.00000000 | 0.00000000
      6 | {beer}          | {diapers}      |     5 | 0.71428571 | 0.71428571 | 1.00000000 | 1.00000000
      1 | {chips}         | {beer}         |     3 | 0.42857143 | 1.00000000 | 1.00000000 | 0.00000000
      3 | {chips,diapers} | {beer}         |     2 | 0.28571429 | 1.00000000 | 1.00000000 | 0.00000000
      7 | {beer,chips}    | {diapers}      |     2 | 0.28571429 | 0.66666667 | 0.93333333 | 0.85714286
      4 | {chips}         | {beer,diapers} |     2 | 0.28571429 | 0.66666667 | 0.93333333 | 0.85714286
      5 | {chips}         | {diapers}      |     2 | 0.28571429 | 0.66666667 | 0.93333333 | 0.85714286
(7 rows)

3. 限制生成关联规则的项集大小为 2

        注意,madlib.assoc_rules 函数总会新创建 assoc_rules 表。如果要保留多个关联规则表,需要在运行函数前备份已存在的 assoc_rules 表。

select * from madlib.assoc_rules( .25,            -- support
                                  .5,             -- confidence
                                  'trans_id',     -- transaction id col
                                  'product',      -- product col
                                  'test_data',    -- input data
                                  null,           -- output schema
                                  true,           -- verbose output
                                  2               -- max itemset size
                                );

select ruleid,     
       pre,            
       post,            
       count,           
       round(support::numeric,8) support,  
       round(confidence::numeric,8) confidence,
       round(lift::numeric,8) lift,
       round(conviction::numeric,8) conviction
  from assoc_rules 
 order by support desc, confidence desc;

        查询结果如下:

 ruleid |    pre    |   post    | count |  support   | confidence |    lift    | conviction 
--------+-----------+-----------+-------+------------+------------+------------+------------
      4 | {diapers} | {beer}    |     5 | 0.71428571 | 1.00000000 | 1.00000000 | 0.00000000
      2 | {beer}    | {diapers} |     5 | 0.71428571 | 0.71428571 | 1.00000000 | 1.00000000
      1 | {chips}   | {beer}    |     3 | 0.42857143 | 1.00000000 | 1.00000000 | 0.00000000
      3 | {chips}   | {diapers} |     2 | 0.28571429 | 0.66666667 | 0.93333333 | 0.85714286
(4 rows)

4. 按需过滤关联规则

        例如,如果想得到规则左端项集只有一个项目,并且规则左端项集为‘beer’:

select * from assoc_rules where array_upper(pre,1) = 1 and post = array['beer'];

        查询结果如下:

 ruleid |    pre    |  post  | count |      support      | confidence | lift | conviction 
--------+-----------+--------+-------+-------------------+------------+------+------------
      4 | {diapers} | {beer} |     5 | 0.714285714285714 |          1 |    1 |          0
      1 | {chips}   | {beer} |     3 | 0.428571428571429 |          1 |    1 |          0
(2 rows)

5. 分析关联规则

        madlib.assoc_rules 函数是根据用户设置的支持度与置信度阈值生成关联规则的。我们以支持度和置信度阈值限制得到了 7 个关联规则,但这些规则的有效性如何呢?前面提到,满足最小支持度和最小置信度的规则,叫做“强关联规则”。然而,强关联规则里,也分有效的强关联规则和无效的强关联规则。

        从提升度来看,提升度大于 1,则规则是有效的强关联规则,否则是无效的强关联规则。如果提升度 =1,说明前提与结果彼此独立,没有任何关联,如果 <1,说明前提与结果是相斥的。以规则 5 为例,提升度为 0.93,说明购买了 diapers 的顾客就不会购买 chips。因此用提升度作为度量,结果中的 7 个规则都是无效的。

参考:

  • 《大数据挖掘——系统方法与实力分析》:讲述关联规则的基本概念及其 Apriori 算法实例。
  • Apriori Algorithm:MADlib 官方文档对 Apriori 算法的说明。
  • Apriori 文档:详细说明如何使用 Apriori 算法找出频繁项集和关联规则。
  • Association rule learning:wiki 上的关联规则学习说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值