关联规则挖掘详解
一、什么是关联规则挖掘
关联规则挖掘(Association Rule Mining)是从大规模数据集中发现项与项之间隐含的共现关系的经典方法。最著名的案例就是"啤酒与尿布"——超市发现购买尿布的年轻父亲经常同时购买啤酒。
核心思想:如果某些项在事务中频繁地一起出现,则它们之间可能存在有价值的关联关系。
事务数据库示例: TID 购买商品 ───────────────────── T1 {面包, 牛奶, 黄油} T2 {面包, 尿布, 啤酒, 鸡蛋} T3 {牛奶, 尿布, 啤酒, 可乐} T4 {面包, 牛奶, 尿布, 啤酒} T5 {面包, 牛奶, 可乐} 挖掘结果: {尿布} → {啤酒} (支持度 60%, 置信度 75%) {面包, 牛奶} → {黄油} (支持度 20%, 置信度 50%)二、核心概念
1. 基本定义
| 概念 | 定义 | 示例 |
|---|---|---|
| 项(Item) | 数据中最小的原子单位 | 面包、牛奶 |
| 项集(Itemset) | 项的集合 | {面包, 牛奶} |
| 事务(Transaction) | 一次事件中出现的项集 | T1: {面包, 牛奶, 黄油} |
| 规则(Rule) | X → Y,X 为前件,Y 为后件 | {面包} → {牛奶} |
2. 三大核心指标
事务总数 N = 5 规则: {尿布} → {啤酒} ├── 包含{尿布}的事务: T2, T3, T4 → 3个 ├── 包含{尿布,啤酒}的事务: T2, T3, T4 → 3个 └── 包含{啤酒}的事务: T2, T3, T4 → 3个| 指标 | 公式 | 计算示例 | 含义 |
|---|---|---|---|
| 支持度 Support | P(X∪Y) = count(X∪Y) / N | 3/5 = 60% | 规则在数据中出现的频率 |
| 置信度 Confidence | P(Y|X) = Support(X∪Y) / Support(X) | 3/3 = 100% | X 出现时 Y 也出现的概率 |
| 提升度 Lift | Confidence(X→Y) / Support(Y) | 1.0 / 0.6 = 1.67 | X 对 Y 出现的提升程度 |
提升度解读:
- Lift = 1:X 与 Y 独立,无关联
- Lift > 1:正相关,X 促进 Y 出现(有价值的规则)
- Lift < 1:负相关,X 抑制 Y 出现
3. 其他重要指标
| 指标 | 公式 | 含义 |
|---|---|---|
| Conviction | (1 - Support(Y)) / (1 - Confidence) | 规则出错的概率比,值越大规则越可靠 |
| Leverage | Support(X∪Y) - Support(X)×Support(Y) | 实际共现与独立假设的差值 |
| Kulc | (Confidence(X→Y) + Confidence(Y→X)) / 2 | 两个方向置信度的均值,对不平衡数据更稳健 |
三、常用算法
算法全景
关联规则挖掘算法 ├── 经典频繁项集挖掘 │ ├── Apriori — 逐层搜索,最经典 │ ├── FP-Growth — 无候选项,模式树,更高效 │ └── Eclat — 垂直数据格式,深度优先 ├── 高效变体 │ ├── LCM — 最快频繁闭项集挖掘 │ ├── Charm — 频繁闭项集,垂直格式 │ └── Mafia — 频繁极大项集 ├── 序列模式挖掘 │ ├── GSP — 广义序列模式 │ ├── PrefixSpan — 前缀投影,更高效 │ └── SPADE — 垂直序列挖掘 └── 多维度/多层扩展 ├── MLTAML — 多层关联规则 └── Quantitative — 量化关联规则1. Apriori 算法 — 最经典
核心思想:先找频繁项集,再生成规则。利用先验性质(Apriori Property):频繁项集的所有子集也必须是频繁的。
逐层搜索过程: 第1轮:扫描数据库,找频繁1-项集 {面包}:3 {牛奶}:4 {尿布}:3 {啤酒}:3 {可乐}:2 {黄油}:1 {鸡蛋}:1 ↓ 过滤 (min_support=40%) L1 = {面包, 牛奶, 尿布, 啤酒, 可乐} 第2轮:L1 自连接 → 候选2-项集,扫描数据库计数 {面包,牛奶}:3 {面包,尿布}:2 {面包,啤酒}:2 {面包,可乐}:1 {牛奶,尿布}:2 {牛奶,啤酒}:2 {牛奶,可乐}:2 {尿布,啤酒}:3 {尿布,可乐}:1 {啤酒,可乐}:1 ↓ 过滤 L2 = {{面包,牛奶}, {尿布,啤酒}, ...} 第3轮:L2 自连接 → 候选3-项集 ... 重复直到无法生成新的频繁项集frommlxtend.frequent_patternsimportapriori,association_rulesimportpandasaspd# 构造布尔事务矩阵transactions=pd.DataFrame({'面包':[1,1,0,1,1],'牛奶':[1,0,1,1,1],'尿布':[0,1,1,1,0],'啤酒':[0,1,1,1,0],'可乐':[0,0,1,0,1],},index=['T1','T2','T3','T4','T5'])# 挖掘频繁项集frequent_items=apriori(transactions,min_support=0.4,# 最小支持度阈值use_colnames=True)print(frequent_items)# 生成关联规则rules=association_rules(frequent_items,metric='confidence',# 评估指标min_threshold=0.6# 最小置信度)# 筛选有价值的规则valuable=rules[(rules['lift']>1.2)&(rules['confidence']>0.7)]print(valuable[['antecedents','consequents','support','confidence','lift']])Apriori 的瓶颈:每轮都要扫描全库,候选项集数量爆炸(特别是 k 较大时)。
2. FP-Growth 算法 — 更高效
核心思想:只需两次扫描数据库,构建 FP 树压缩存储,直接在树上挖掘频繁模式,无需生成候选项集。
FP 树构建过程: 第1次扫描:统计频次,按频次降序排列项 牛奶:4 > 面包:3 > 尿布:3 = 啤酒:3 > 可乐:2 第2次扫描:将每条事务按频次顺序插入树 ∅ (root) / \ 牛奶 面包 / | \ \ 面包 尿布 可乐 尿布 | | | 尿布 啤酒 啤酒 | 啤酒 节点记录: 项名 + 计数 + 链接(同项节点串联)frommlxtend.frequent_patternsimportfpgrowth,association_rules# FP-Growth 挖掘频繁项集(API 与 apriori 一致,内部更高效)frequent_items=fpgrowth(transactions,min_support=0.4,use_colnames=True)# 生成规则(与 Apriori 后续步骤相同)rules=association_rules(frequent_items,metric='confidence',min_threshold=0.6)Apriori vs FP-Growth 对比:
| 维度 | Apriori | FP-Growth |
|---|---|---|
| 数据库扫描次数 | k+1 次(k 为最大项集长度) | 2 次 |
| 候选项集 | 需要生成,可能爆炸 | 无需生成 |
| 内存占用 | 候选项集可能很大 | FP 树压缩存储 |
| 适用场景 | 项集较短、稀疏数据 | 项集较长、密集数据 |
| 实现复杂度 | 简单 | 较复杂 |
3. Eclat 算法 — 垂直数据格式
核心思想:将水平事务格式转为垂直格式(项 → TID 列表),通过 TID 集合交集计算支持度,深度优先搜索。
水平格式 → 垂直格式转换: 水平: 垂直: T1: {面包,牛奶} 面包: {T1,T2,T4,T5} T2: {面包,尿布,啤酒} 牛奶: {T1,T3,T4,T5} T3: {牛奶,尿布,啤酒} 尿布: {T2,T3,T4} T4: {面包,牛奶,尿布,啤酒} 啤酒: {T2,T3,T4} T5: {面包,牛奶,可乐} 可乐: {T3,T5} 计算 {尿布,啤酒} 的支持度: 尿布 ∩ 啤酒 = {T2,T3,T4} ∩ {T2,T3,T4} = {T2,T3,T4} Support = 3/5 = 60%# mlxtend 不直接支持 Eclat,可用 pyfim 或手动实现# 简化版 Eclat 实现defeclat(vertical_db,min_support,N):"""vertical_db: {item: set_of_tids}"""frequent={}defdfs(prefix,items,tids):foriteminsorted(items):new_tids=tids&vertical_db[item]iftidselsevertical_db[item]iflen(new_tids)/N>=min_support:new_prefix=prefix+[item]frequent[frozenset(new_prefix)]=len(new_tids)remaining={iforiinitemsifi>item}dfs(new_prefix,remaining,new_tids)dfs([],set(vertical_db.keys()),set())returnfrequent# 使用vertical_db={'面包':{1,2,4,5},'牛奶':{1,3,4,5},'尿布':{2,3,4},'啤酒':{2,3,4},'可乐':{3,5}}result=eclat(vertical_db,min_support=0.4,N=5)| 维度 | Apriori | FP-Growth | Eclat |
|---|---|---|---|
| 搜索策略 | 广度优先 | 深度优先 | 深度优先 |
| 数据格式 | 水平 | 压缩树 | 垂直 |
| 扫描次数 | 多次 | 2次 | 1次(预转换后) |
| 内存 | 候选集 | FP树 | TID集合 |
| 适合 | 通用 | 密集长模式 | 稀疏短模式 |
4. 序列模式挖掘 — PrefixSpan
当项之间有时间顺序时,需要序列模式挖掘:
# 序列数据库:每个序列是按时间排列的项集sequences=[[['面包'],['牛奶','黄油'],['啤酒']],# 顾客A的购买序列[['面包','牛奶'],['尿布'],['啤酒','可乐']],# 顾客B[['牛奶'],['尿布','啤酒'],['可乐']],# 顾客C]# 规则: {面包} → {牛奶} → {啤酒} (先买面包,再买牛奶,最后买啤酒)四、完整实战案例
importpandasaspdfrommlxtend.frequent_patternsimportfpgrowth,association_rulesfrommlxtend.preprocessingimportTransactionEncoder# 1. 原始事务数据transactions=[['面包','牛奶','黄油'],['面包','尿布','啤酒','鸡蛋'],['牛奶','尿布','啤酒','可乐'],['面包','牛奶','尿布','啤酒'],['面包','牛奶','可乐'],['尿布','啤酒','可乐'],['面包','牛奶','尿布','可乐'],['面包','尿布','啤酒'],]# 2. 编码为布尔矩阵te=TransactionEncoder()te_ary=te.fit(transactions).transform(transactions)df=pd.DataFrame(te_ary,columns=te.columns_)# 3. FP-Growth 挖掘频繁项集frequent_items=fpgrowth(df,min_support=0.25,use_colnames=True)frequent_items['length']=frequent_items['itemsets'].apply(len)print("=== 频繁项集 ===")print(frequent_items.sort_values('support',ascending=False))# 4. 生成关联规则rules=association_rules(frequent_items,metric='lift',min_threshold=1.0)# 5. 多条件筛选有价值的规则valuable_rules=rules[(rules['support']>=0.25)&(rules['confidence']>=0.6)&(rules['lift']>=1.2)].sort_values('lift',ascending=False)print("\n=== 高价值关联规则 ===")print(valuable_rules[['antecedents','consequents','support','confidence','lift']].to_string())# 6. 可视化importmatplotlib.pyplotasplt plt.figure(figsize=(10,6))scatter=plt.scatter(rules['support'],rules['confidence'],c=rules['lift'],cmap='YlOrRd',alpha=0.7,s=80)plt.colorbar(scatter,label='Lift')plt.xlabel('Support')plt.ylabel('Confidence')plt.title('Association Rules: Support vs Confidence (color=Lift)')plt.tight_layout()plt.show()五、应用场景
| 领域 | 应用 | 示例规则 |
|---|---|---|
| 零售/电商 | 购物篮分析、商品推荐 | {手机壳} → {手机膜} Lift=3.2 |
| 金融 | 交叉销售、欺诈模式 | {大额转账, 境外IP} → {欺诈} |
| 医疗 | 症状-疾病关联、药物配伍 | {头痛, 发热} → {流感} |
| Web 挖掘 | 页面共访、导航路径 | {首页, 搜索页} → {商品详情页} |
| 网络运维 | 故障关联分析 | {CPU飙升, 磁盘IO高} → {服务超时} |
| 教育 | 知识点关联、学习路径 | {函数, 循环} → {递归} |
六、实践要点与常见误区
| 要点 | 说明 |
|---|---|
| 最小支持度不宜过高 | 过高会漏掉有价值的低频规则,建议从低阈值开始逐步调高 |
| 提升度比置信度更重要 | 置信度高但提升度 ≤1 的规则无意义(Y 本身就很频繁) |
| 关注规则的可操作性 | 规则必须有业务含义,{牛奶}→{面包} 可能只是两者都畅销 |
| 避免冗余规则 | {A,B}→{C} 和 {A}→{C} 可能表达同一关系,优先保留更简洁的 |
| 时间维度 | 购物篮分析中,同一购物车 ≠ 同一意愿,需结合时间窗口 |
| 数据预处理 | 稀疏项可合并归类(如"红苹果"“绿苹果"→"苹果”),减少项数提升效率 |
| 负关联同样重要 | Lift < 1 的负关联(互斥关系)也有业务价值,如{高端产品}→{折扣商品} |