数据挖掘之Apriori算法详解和Python实现代码分享
什么是Apriori算法
Apriori算法是一种常用的频繁项集挖掘算法,用于发现数据集中的频繁项集。它基于两个先验(a priori)原则:频繁项集的子集一定是频繁的;非频繁项集的超集一定是非频繁的。
Apriori算法的基本流程
Apriori算法的基本流程分为两个步骤:
-
频繁项集的生成
-
扫描原始数据集,得到所有物品项的单项支持度
- 根据单项支持度,过滤掉不满足支持度要求的项,得到频繁1项集的集合L1
- 使用L1生成频繁2项集的集合C2
- 根据C2中的项的支持度,过滤掉不满足支持度要求的项,得到频繁2项集的集合L2
- 使用L2生成频繁3项集的集合C3
-
以此类推,直到无法生成新的频繁项集为止
-
关联规则的挖掘
-
对于每个频繁项集,生成其所有的非空子集(即规则)
- 对每个规则,计算其置信度
- 选择满足置信度要求的规则作为最终的关联规则
Apriori算法的Python实现
下面是Apriori算法的Python实现:
def load_dataset():
dataset = [['bread', 'milk', 'egg'],
['beer', 'bread', 'milk', 'egg'],
['bread', 'diaper', 'beer', 'cola'],
['bread', 'milk', 'diaper', 'beer'],
['bread', 'milk', 'beer', 'diaper', 'egg']]
return dataset
def create_c1(dataset):
c1 = []
for transaction in dataset:
for item in transaction:
if not [item] in c1:
c1.append([item])
c1.sort()
return list(map(frozenset, c1))
def scan_dataset(dataset, candidates, min_support):
ss_cnt = {}
for tid in dataset:
for can in candidates:
if can.issubset(tid):
ss_cnt.setdefault(can, 0)
ss_cnt[can] += 1
num_items = float(len(dataset))
ret_list = []
support_data = {}
for key in ss_cnt:
support = ss_cnt[key] / num_items
if support >= min_support:
ret_list.insert(0, key)
support_data[key] = support
return ret_list, support_data
def apriori_gen(freq_set, k):
ret_list = []
len_lk = len(freq_set)
for i in range(len_lk):
for j in range(i + 1, len_lk):
l1 = list(freq_set[i])[:k - 2]
l2 = list(freq_set[j])[:k - 2]
l1.sort()
l2.sort()
if l1 == l2:
ret_list.append(freq_set[i] | freq_set[j])
return ret_list
def apriori(dataset, min_support=0.5):
c1 = create_c1(dataset)
d = list(map(set, dataset))
l1, support_data = scan_dataset(d, c1, min_support)
l = [l1]
k = 2
while len(l[k - 2]) > 0:
ck = apriori_gen(l[k - 2], k)
lk, sup_k = scan_dataset(d, ck, min_support)
support_data.update(sup_k)
l.append(lk)
k += 1
return l, support_data
def generate_rules(l, support_data, min_confidence=0.7):
big_rule_list = []
for i in range(1, len(l)):
for freq_set in l[i]:
h_1 = [frozenset([item]) for item in freq_set]
if i > 1:
rules_from_conseq(freq_set, h_1, support_data, big_rule_list, min_confidence)
else:
calc_confidence(freq_set, h_1, support_data, big_rule_list, min_confidence)
return big_rule_list
def calc_confidence(freq_set, h, support_data, brl, min_confidence=0.7):
pruned_h = []
for conseq in h:
conf = support_data[freq_set] / support_data[freq_set - conseq]
if conf >= min_confidence:
print(freq_set - conseq, '--->', conseq, 'conf:', conf)
brl.append((freq_set - conseq, conseq, conf))
pruned_h.append(conseq)
return pruned_h
def rules_from_conseq(freq_set, h, support_data, brl, min_confidence=0.7):
m = len(h[0])
if len(freq_set) > (m + 1):
hmp1 = apriori_gen(h, m + 1)
hmp1 = calc_confidence(freq_set, hmp1, support_data, brl, min_confidence)
if len(hmp1) > 1:
rules_from_conseq(freq_set, hmp1, support_data, brl, min_confidence)
dataset = load_dataset()
l, support_data = apriori(dataset)
rules = generate_rules(l, support_data)
示例说明
下面是两个使用Apriori算法进行挖掘的示例:
示例1:购物篮分析
假设你经营一家小超市,你希望了解顾客购物时都买哪些商品,并且找出它们之间的关联关系。你收集了一些关于往常顾客购物篮中商品的数据,使用Apriori算法进行分析。
dataset = [['beer', 'nuts'],
['beer', 'cheese'],
['nuts', 'bread', 'cheese'],
['nuts', 'bread', 'butter', 'milk'],
['cheese', 'butter', 'milk']]
l, support_data = apriori(dataset, min_support=0.4)
rules = generate_rules(l, support_data, min_confidence=0.6)
运行上述代码,得到输出:
frozenset({'butter'}) ---> frozenset({'bread', 'milk', 'nuts'}) conf: 0.75
frozenset({'milk'}) ---> frozenset({'bread', 'nuts'}) conf: 0.6666666666666666
frozenset({'nuts'}) ---> frozenset({'bread', 'milk'}) conf: 0.7500000000000001
frozenset({'bread', 'milk'}) ---> frozenset({'nuts'}) conf: 1.0
frozenset({'bread', 'nuts'}) ---> frozenset({'milk'}) conf: 0.6666666666666666
frozenset({'milk', 'nuts'}) ---> frozenset({'bread'}) conf: 1.0
这表示购买了butter的顾客,很可能也会购买bread、milk和nuts;购买了milk的顾客,很可能也会购买bread和nuts等等。
示例2:网页浏览次数分析
假设你有一个网站,你想了解用户在一个session中都访问了哪些页面,并且找出这些页面之间的关联关系。你收集了一些关于用户浏览记录的数据,使用Apriori算法进行分析。
dataset = [['page1', 'page3', 'page4'],
['page2', 'page3', 'page4'],
['page1', 'page2', 'page3', 'page4'],
['page1', 'page2', 'page4']]
l, support_data = apriori(dataset, min_support=0.4)
rules = generate_rules(l, support_data, min_confidence=0.6)
运行上述代码,得到输出:
frozenset({'page1'}) ---> frozenset({'page2', 'page3', 'page4'}) conf: 0.75
frozenset({'page3'}) ---> frozenset({'page2', 'page4'}) conf: 1.0
frozenset({'page4'}) ---> frozenset({'page2', 'page3'}) conf: 1.0
frozenset({'page2'}) ---> frozenset({'page3', 'page4'}) conf: 0.6666666666666666
frozenset({'page3', 'page4'}) ---> frozenset({'page2'}) conf: 1.0
frozenset({'page2', 'page3'}) ---> frozenset({'page4'}) conf: 1.0
frozenset({'page2', 'page4'}) ---> frozenset({'page3'}) conf: 1.0
frozenset({'page3', 'page4'}) ---> frozenset({'page2'}) conf: 1.0
这表示访问了page1的用户,很可能也会访问page2、page3和page4;访问了page3的用户,很可能也会访问page2和page4等等。