机器学习算法基本型 关联规则(笔记)

 

引言

有一个很经典的例子:超市里面发现,尿布和啤酒,经常出现在同一张购物单上。这两个毫不相干的事情,为什么会产生联系?后来发现,原来是因为,有时候母亲在家中照看婴儿,父亲会去超市购买尿布。父亲在购买尿布的同时,往往会顺便为自己购买啤酒,这样,啤酒与尿布这两件看上去不相干的商品,就经常会出现在同一个购物篮中。这就是一个关联规则。

关联规则能解决什么问题?

比如,上面的例子,我们或许就可以解决三个问题:

1、我想卖得更好的产品,谁能带动它?
2、我现在的爆品,能带动谁?
3、哪些商品组合在一起能创造新的消费场景?
 
进一步的,可以考虑商品的排布,库存的管理,供应链的优化。找到事物之间的关系,找到他们的相关性,就可以刻画我们需要的样子。

相关概念

假设,我们知道上述例子的一些统计信息:

image

 支持度(Support)

image

 两者共同出现次数占总销售次数的比例。比如 n2是5次购买中,购买尿布的次数,为3;n3是5次购买中,购买啤酒的次数,为4;n1为n2和n3的交集,即同时购买尿布和啤酒的次数,为3;n4为购买的总次数,为5。所以,购买{尿布} 也会 购买{啤酒}的支持程度:n1/n4 = 3/5 ,即:60%的交易中他们共同出现了。这里注意,支持度衡量的是两者同时出现的次数,所以分子是交集,结果具有对称性。即购买尿布也会购买啤酒的支持度,和购买啤酒也会购买尿布的支持度,是一样的。使用时,可以设置最小支持度,来过滤一些不需要的规则。

置信度(Confidence)

那么,究竟是啤酒促进了尿布的销量,还是尿布促进了啤酒的销量呢?这就通过置信度来衡量的:两者共同出现次数占前者出现次数的比例。

{尿布}-->{啤酒}的置信度:n1/n2 = 3/3;

{啤酒}-->{尿布}的置信度:n1/n3 = 3/4;

所以,{尿布}-->{啤酒},比 {啤酒}-->{尿布} 更让人信服,也就是买尿布的更可能同时也买啤酒,而买啤酒的也去买尿布的情况,概率没那么大。使用时,可以设置最小置信度,来过滤一些不需要的规则。

强相关?负相关?

假设使用一个用于发现关联规则的数据挖掘程序,设定 最小支持度(support)为 30%,最小置信度(confidence)为 60%。 根据计算,能够发现如下的规律,即买电脑游戏的,也会买视频的这条规则,支持度为40%,置信度为66% :

image

 然而,这条规则是具有误导性的,因为单独购买视频的概率是75%,甚至高于规则中所显示的 66%。这意味,如果我买了电脑游戏,反而会令视频的购买量下降。电脑游戏和视频之间是负相关的!如果没有充分理解这一现象,就很容易根据上面的规则做出不明智的商业决策。同时也说明,关联规则 A ⇒ B 的置信度(confidence)具有欺骗性,它并不能唯一地去衡量 A 和 B 之间相关性或因果关系的强度。因此,在数据挖掘中,除了传统的支持度–置信度(support–confidence)框架之外,同时也使用其他指标或方法来发现更有意义的数据关系也是十分必要的。

转化效率/提升度(Lift)

为了避免上面的负相关问题,了解真正可以促进销售的关系,引入了这个概念:转化效率/提升度(Lift)。Lift = 置信度 / 后者在总销售记录的比例 ,针对 {尿布}-->{啤酒} 的数据关系,Lift = (n1/n2) / (n3/n4) ,即:

1、{尿布} --> {啤酒}的置信度 = 3/3
2、啤酒的出现比例:4/5
3、Lift = 3/3 / 4/5 = 1.25
 
因此,就可以继续了解,买了尿布,再购买其他产品的可能性,谁比较大。比如 {尿布} --> {巧克力} 的Lift如下:
1、{尿布} --> {巧克力}的自信心 = 2/3
2、巧克力的出现比例:3/5
3、Lift = 2/3 / 3/5 = 1.11
 
进而得出,消费者买了尿布以后,再买啤酒的概率大于再买巧克力的概率。
 
Lift 的衡量标准
• 若计算结果 小于 1,则表示 A 与 B 负相关,即一个项集的出现往往意味着另一个项集不出现
• 若计算结果 大于 1,则表示 A 与 B 正相关,即一个项集的出现暗示另一个项集也有可能出现
• 若计算结果 等于 1,则表示 A 与 B 相互独立两者之间不存在相关性
 
这时候就需要思考一个问题:那是不是本身一个事物的概率就高,所以 Lift 才高?特别是当 Lift 仅仅是略微大于 1 时,我们能不能说 "就是A 导致了 B 更可能出现"?极有可能是不一定的。可能只是 B 是高频商品(概率 P(B) 本来就很大,直接拉高了 Lift (A|B)),或者样本量不够(样本太少,多一笔交易就可能把Lift拉到1以下),甚至可能是存在辛普森悖论(整体数据呈现的趋势,与分组后各组内部呈现的趋势完全相反。比如整体购买B的概率是85%,买A就买B的概率是90%,在这个数据关系中,Lift大于1。但如果根据性别进一步分组会发现,女性中,买A就买B的概率是80%,整体购买B的概率是83%,Lift其实<1。如果你根据整体Lift结论,去给女性这样推销,极有可能会适得其反,没有达到你想要的效果)。
 
所以,只有Lift,依然不能唯一地得出相关性结论,依然需要结合:

• 检查B的基础概率(太高时Lift容易被夸大)

• 检查样本量(太小时Lift不稳定)

• 是否存在混杂因素,如时间/季节/性别等,进一步进行分组分析(辛普森悖论)

 

因此,在数据挖掘中,构建模型,得出一个关系结论,一定要结合各种指标去判断它是否可靠,比如支持度、置信度、提升度、确信度、卡方检验等。而即使基于很多指标,判断这个关系足够靠谱,也依然要持怀疑态度,明白它可能并非100%正确的。它只是,相对靠谱。带着这种“相对靠谱”的结论去做决策时,要考虑容错机制,要有A/B测试验证的测试策略,要持续监控效果。数据挖掘不是寻找真理,而是构建一个“当前证据下最靠谱的假设”,然后用业务实践去检验它。

 

关联规则算法--Apriori算法

相关概念

1、项(Item):每一个可被购买或出现的对象称为一个项(Item);

2、项集(Itemset):一组项的集合称为项集(Itemset)。例如:{尿布,啤酒} 是一个 2-项集(包含2个项),{冰淇淋, 尿布, 啤酒} 是一个 3-项集;
3、频繁项集(Frequent Itemset):若一个项集在事务数据库中出现的支持度大于等于预设的最小支持度阈值,则称该项集为频繁项集(Frequent Itemset)。一个频繁项集的所有非空子集也是频繁项集。逆否命题是:如果一个项集不是频繁项集,那么它的扩集也不是频繁项集。

算法流程

Apriori算法命名源于算法使用了频繁项集性质的先验(Prior)知识。利用此方法,发现关联规则。
Tips:0-1矩阵(也叫二元矩阵或布尔矩阵),是关联规则挖掘(Apriori算法等)的标准输入格式。矩阵里只有两个数字:0(False,未发生),1(True,发生)。
 
 
image

 算法发现关联规则的计算过程

假设数据集有9笔交易, |D|= 9。最小支持次数为2。

image

 

 第一次迭代:每个单个项都被视为一个候选1-项集C1的成员。对C1中的每一个候选1-项集进行扫描,统计C1中每个项在数据集中出现的次数(即支持计数)。筛选出满足最小支持计数的候选项,生成频繁1-项集。

image

 第二次迭代:算法通过对 L1*L1 进行连接操作,生成一个候选2-项集。对C2中的每一个候选2-项集进行扫描,统计C2中每个项在数据集中出现的次数(即支持计数)。筛选出满足最小支持计数的候选项,生成频繁2-项集。

image

 第三次迭代:算法通过对 L2*L2 进行连接操作,生成一个候选3-项集。此时每个项有3项,开始存在非频繁的非空子集。此次迭代,我们是为了求得频繁3-项集。所以为了提高算法效率,根据频繁项集的每个非空子集也必须是频繁的,对当前候选3-项集中,已经存在非频繁非空子集的3-项集进行剪裁。

Tips:快速比对是否存在非频繁子集,可以对每个候选3-项集的非空2-项子集,直接和频繁2-项集L2比对,非空2-项子集没有出现在L2的候选3-项集,就可以直接裁剪了,不需要和原数据集挨个比对了。

image

 对剪裁后的C3中的每一个候选3-项集进行扫描,统计C3中每个项集在数据集中出现的次数(即支持计数)。筛选出满足最小支持计数的候选项,生成频繁3-项集。

image

  第四次迭代:算法通过对 L3*L3 进行连接操作,生成一个候选4-项集 C4 = {I1,I2,I3,I5}。和频繁3-项集L3比对,{I2,I3,I5}不在L3中,所以直接剪裁。此时,C4 = ∅,无候选4-项集,本次不需要再次迭代,算法终止。所有频繁项集均已被发现,即:L1,L2,L3。

  根据频繁项集生成强关联规则:频繁项集被发现后,生成强关联规则就变得非常直接。强关联规则,必须同时满足最小支持度和最小置信度。对每个频繁项集 X,可以生成规则:A⇒(X−A),∀A⊂X,A不为∅。其中 A 是 X 的非空子集,X − A 是剩余项集。也就是通过A,可以发现 X-A 。由于规则是从频繁项集生成的,每条规则天然满足最小支持度,只需检查置信度。若置信度 ≥ 最小置信度,则该规则为强关联规则。比如,对{I1, I2, I5 },所有非空子集为{I1, I2}, {I1,I5}, {I2, I5}, {I1}, {I2 }, {I5 }.根据置信度公式,交集/前项的概率,这里都用次数,可以得到每个关系的置信度结果。这其中,置信度大于等于要求的关系,就是强关联规则,比如我要求大于等于50%,那么第4,5条就不符合,可以剪除了:

image

 同样的方法,依次得到每个频繁项集中,满足要求的强关联规则。

Apriori算法的瓶颈

1、宽度优先(逐层)搜索:可能需要生成大量候选集。如,若存在10的四次方个频繁1项集,Apriori算法可能需要生成超过10的七次方个候选 2项集;

2、频繁扫描数据库:需要多次扫描整个数据库,对大量候选集进行模式匹配检查;

3、计算开销大:需要遍历每条事务记录来计算候选项集的支持度,成本较高。

因此,Apriori算法适用于数据量适中、更新不频繁、需要挖掘明确关联规则的离线分析场景。

关联规则算法--FP-Growth算法

一种基于频繁模式增长(Frequent Pattern-Growth)的挖掘方法,是Apriori算法的改进。FP-Growth算法,采用深度优先的搜索策略,无需候选项集生成,即可发现频繁项集。它是利用局部频繁项,从短模式逐步增长成长模式,仅在条件数据库中进行挖掘,避免全局候选爆炸。

算法流程

1. 对于每一个频繁项,构建其条件模式基,并据此构建条件 FP-tree;
2. 对每一个新生成的条件 FP-tree 重复上述过程;
3. 直到生成的 FP-tree 为空,或仅包含一条路径。对于单条路径,可生成其所有子路径的组合,每个组合都是一个频繁模式。

算法发现关联规则的计算过程

依然基于这个例子进行说明。

image

 

1、数据库的第一次扫描与 Apriori 方法相同,用于得到频繁项(1-项集)及其支持度计数(出现频次)。这里,最小支持度阈值:min_sup = 2.将所有频繁项按照支持度计数从高到低进行排序,得到的频繁项集合(或列表)记为 L:L ={{I2: 7 }, {I1: 6 }, {I3: 6 }, {I4: 2 },{I5: 2 }} ;
2、构建FP-tree :
1)创建一棵树的根节点,标记为“null”;
2)对数据库 D 进行第二次扫描;
3)对于每一条事务,其包含的项按照 L 中的顺序进行处理(即按照支持度计数从高到低排序),比如T100,原来是{I1,I2,I5},重新排序为“{I2,I1,I5}”。如果某个T里面,所有项都不在L中,则直接被剪除;

image

 4)对上述重排后的每一条事务都会在 FP-tree 中创建一条分支。为了便于对 FP-tree 的遍历,构建了一个项头表(item headertable),使得每个项可以通过节点链(node-links)指向其在树中所有出现的位置。扫描完所有事务后得到的 FP tree,以及与之对应的节点链,如图所示:

image

 

通过这种方式,在数据库中挖掘频繁模式的问题就被转化为在FP-tree 上挖掘频繁模式的问题。
3、FP-tree的挖掘过程如下:
1)从每个频繁的长度 1 模式开始,作为初始后缀模式(initial suffixpattern)。首先考虑 I5,它是列表 L 中的最后一项。 I5 出现在 FP-tree 的两个分支中:
• <I2, I1, I5: 2>
• <I2, I1, I3, I5: 1>
2)将 I5 视为后缀(suffix),其对应的两个前缀路径(prefix paths)形成其条件模式基(conditional pattern base):
• <I2, I1: 2>
• <I2, I1, I3: 1>
3)以此条件模式基作为事务数据库,构建 I5 条件 FP-tree。该条件 FP-tree 仅包含一条路径:<I2:2, I1: 2>。<I2, I1, I3: 1> 不被包含,因为其支持度为 1,小于最小支持度阈值(min_sup = 2)。这条单路径可以生成所有可能的频繁模式组合:
• {I2, I5: 2}
• {I1, I5: 2}
• {I2, I1, I5: 2}
4)同样的方式,再考虑I4和I3、I1,分别生成频繁模式。注意,I2作为最高支持度,最靠近根节点的节点,是不需要单独考虑的。因为它已经隐含在其他节点的挖掘结果里了。这是 FP-Growth 算法设计的高明之处——既保证不丢任何模式,又避免重复计算:
 
I4:
前缀路径(prefix paths)形成条件模式基: {{I2,I1:1},{I2:1}}
基于该条件模式基构建条件 FP-tree: <I2:2>
由此生成的频繁模式为: {I2,I4:2}
 
I3
前缀路径(prefix paths)形成条件模式基:  {{ I2, I1: 2}, {I2: 2 }, {I1: 2 }}
基于该条件模式基构建的条件 FP-tree: <I2: 4, I1: 2> and <I1: 2>
由此生成的频繁模式为 {{ I2, I3: 4}, {I1,I3: 4}, {I2, I1, I3: 2 }} 
 
I1
前缀路径(prefix paths)形成条件模式基: {{ I2: 4 }}
基于该条件模式基构建的条件 FP-tree: <I2: 4>
由此生成的频繁模式为: {I2, I1: 4}
 
整理后得到下表:

image

 

FP-Growth算法的特点

• FP-growth 方法将寻找长频繁模式的问题,转化为在更小的条件数据库中递归搜索的短模式,然后将结果与后缀进行连结;
• 它通常将最不频繁的项作为后缀,从而具有较好的选择性。“选择性”指的是一个条件或约束能够过滤掉多少数据。比如:
  • 高选择性 = 在全校找“身高2.2米以上的人”(很少)

  • 低选择性 = 在全校找“身高1.6米以上的人”(很多)

FP-Growth采用从低频到高频的处理顺序:先处理最不频繁的项(I5、I4),后处理较频繁的项(I3、I1),不处理最高频的项(I2)。这也是FP算法提升效率的核心,可以快速剪枝、快速收敛、避免指数级爆炸。FP-tree 的大小不会超过原始数据库(不计节点链和计数字段,因为这是为了让算法高效运行而附加的“工具”或“元数据”,与树的规模无关),它以前缀路径为单位存储,将所有事务中相同的前缀合并。比如,I2作为根节点下的第一个节点,无论它在多少条事务中出现,在每棵FP树中只存一次,只是把它的计数(count)设为7。FP-tree通过共享前缀,消除了原始数据中项在事务间的重复存储;

• 该方法显著降低了搜索成本,避免了 Apriori 中大量候选集生成与多次数据库扫描的问题。
 
当数据库规模较大时,直接构建基于主存的 FP-tree 有时并不现实。一个可行的替代方法是: 将数据库划分为一组投影数据库(projected databases)。对每个投影数据库构建 FP-tree 并进行挖掘。如果某个投影数据库的 FP-tree 仍然无法放入主存,则可以递归地对该投影数据库重复该过程。

image

 

对 FP-growth 方法性能的研究表明:
• 它在挖掘长频繁模式和短频繁模式方面都表现出高效性和可扩展性;
• 相比 Apriori 算法,FP-growth 的速度大约快一个数量级。在低支持度中的表现,运行时间也远比Apriori要平缓。

image

 

关联算法在WEKA里的指标说明

image

 

posted @ 2026-02-27 17:42  1234roro  阅读(27)  评论(0)    收藏  举报