从啤酒尿布到机器学习:用Python实战关联规则,5分钟看懂Apriori算法核心
超市货架上啤酒和尿布的经典组合,背后隐藏着数据挖掘领域最著名的商业案例之一。这种通过分析消费者购买行为来发现商品间隐藏关联的技术,正是关联规则挖掘的核心应用。本文将带你从零开始,用Python实现Apriori算法,揭开"啤酒与尿布"现象背后的数学原理。
1. 关联规则挖掘的商业智慧
1990年代,沃尔玛的分析师发现了一个有趣现象:周五晚上,年轻父亲们经常在购买尿布的同时顺手拿上几罐啤酒。这个发现催生了零售业经典的"啤酒+尿布"促销策略,也成为关联规则挖掘最成功的商业案例。
关联规则挖掘要解决的核心问题是:如何从海量交易数据中发现商品之间的潜在联系?这需要两个关键指标:
- 支持度(Support): 规则X→Y在所有交易中出现的频率
- 置信度(Confidence): 包含X的交易中也包含Y的条件概率
用数学表达式表示:
支持度(X→Y) = P(X∩Y) 置信度(X→Y) = P(Y|X) = P(X∩Y)/P(X)2. Apriori算法原理拆解
Apriori算法是关联规则挖掘的经典方法,其核心思想基于一个简单先验知识:频繁项集的所有子集也必须是频繁的。这个性质被称为Apriori性质,它大幅减少了需要计算的项集组合。
算法主要分为两个阶段:
- 频繁项集生成:找出所有满足最小支持度的商品组合
- 规则生成:从频繁项集中提取高置信度的关联规则
2.1 频繁项集生成过程
让我们用Python代码演示如何生成频繁项集:
from itertools import combinations def generate_frequent_itemsets(transactions, min_support): items = set(item for transaction in transactions for item in transaction) itemsets = [frozenset([item]) for item in items] frequent_itemsets = [] k = 1 while itemsets: # 计算候选项集支持度 candidate_counts = {} for transaction in transactions: for itemset in itemsets: if itemset.issubset(transaction): candidate_counts[itemset] = candidate_counts.get(itemset, 0) + 1 # 筛选满足最小支持度的项集 frequent_k_itemsets = [] num_transactions = len(transactions) for itemset, count in candidate_counts.items(): support = count / num_transactions if support >= min_support: frequent_k_itemsets.append(itemset) frequent_itemsets.extend(frequent_k_itemsets) # 生成下一轮候选项集 itemsets = set() for i in range(len(frequent_k_itemsets)): for j in range(i+1, len(frequent_k_itemsets)): new_itemset = frequent_k_itemsets[i].union(frequent_k_itemsets[j]) if len(new_itemset) == k + 1: itemsets.add(new_itemset) itemsets = list(itemsets) k += 1 return frequent_itemsets2.2 关联规则提取
获得频繁项集后,我们可以从中提取关联规则:
def generate_rules(frequent_itemsets, transactions, min_confidence): rules = [] for itemset in frequent_itemsets: if len(itemset) < 2: continue subsets = [] for i in range(1, len(itemset)): subsets.extend(combinations(itemset, i)) for antecedent in subsets: antecedent = frozenset(antecedent) consequent = itemset - antecedent # 计算支持度和置信度 antecedent_count = sum(1 for t in transactions if antecedent.issubset(t)) rule_support = sum(1 for t in transactions if itemset.issubset(t)) / len(transactions) if antecedent_count > 0: confidence = rule_support / (antecedent_count / len(transactions)) if confidence >= min_confidence: rules.append((antecedent, consequent, rule_support, confidence)) return rules3. 实战:超市购物篮分析
让我们用一个实际数据集演示完整的关联规则挖掘流程。假设我们有以下交易数据:
| 交易ID | 商品 |
|---|---|
| 1 | 牛奶,面包,尿布 |
| 2 | 可乐,面包,尿布 |
| 3 | 牛奶,尿布,啤酒 |
| 4 | 面包,牛奶,尿布,啤酒 |
| 5 | 面包,牛奶,尿布 |
首先,我们需要将数据转换为适合处理的格式:
transactions = [ {'牛奶', '面包', '尿布'}, {'可乐', '面包', '尿布'}, {'牛奶', '尿布', '啤酒'}, {'面包', '牛奶', '尿布', '啤酒'}, {'面包', '牛奶', '尿布'} ]然后应用Apriori算法:
# 设置最小支持度为40%,最小置信度为70% min_support = 0.4 min_confidence = 0.7 # 生成频繁项集 frequent_itemsets = generate_frequent_itemsets(transactions, min_support) # 生成关联规则 rules = generate_rules(frequent_itemsets, transactions, min_confidence) # 按置信度排序 rules.sort(key=lambda x: x[3], reverse=True) # 输出前5条规则 for i, (antecedent, consequent, support, confidence) in enumerate(rules[:5]): print(f"规则 {i+1}: {antecedent} → {consequent}") print(f"支持度: {support:.2f}, 置信度: {confidence:.2f}") print()执行结果可能如下:
规则 1: {'尿布'} → {'牛奶'} 支持度: 0.80, 置信度: 1.00 规则 2: {'牛奶'} → {'尿布'} 支持度: 0.80, 置信度: 1.00 规则 3: {'面包'} → {'尿布'} 支持度: 0.80, 置信度: 1.00 规则 4: {'尿布', '面包'} → {'牛奶'} 支持度: 0.60, 置信度: 1.00 规则 5: {'牛奶', '面包'} → {'尿布'} 支持度: 0.60, 置信度: 1.004. 算法优化与扩展应用
基础Apriori算法虽然直观,但在处理大规模数据时效率较低。以下是几种常见的优化方法:
- FP-Growth算法:使用频繁模式树(FP-tree)结构,避免生成候选项集
- 垂直数据格式:记录每个项集出现在哪些交易中,加速支持度计算
- 并行计算:利用MapReduce等框架分布式处理大规模数据
关联规则挖掘的应用远不止零售行业:
- 医疗领域:发现疾病与症状、药物之间的关联
- 网络安全:识别异常行为模式
- 推荐系统:基于用户行为推荐相关内容
提示:在实际应用中,除了支持度和置信度,还可以考虑提升度(Lift)等指标来评估规则质量。提升度衡量规则中项集的相关性,计算公式为:Lift(X→Y) = P(Y|X)/P(Y)