本文使用的源码以及数据集Data-Mining/Apriori at Stellaris.github.io · Stellaris123/Data-Mining
Apriori
Apriori 算法采用的策略是将数管来拿规则挖掘任务分为①产生频繁项集、②产生规则,两主要步骤。
详细步骤
一、产生频繁项集:从数据中发现满足最小支持度阈值的所有项集。
(1)确定数据集
(2)将候选集中每个项目单独进行扫描,根据支持度公式进行计算支持度,并筛掉不满足设定的最小支持度阈值的项。
(3)从项集生成候选 项集:判断 项集中每两个的项中是否满足两个项的
(4)将候选 项集进行筛选,产生
(5)重复 3~4 步骤直到项集小于等于 1。
二、从产生的频繁项集中找出满足最小置信度阈值的规则。
(1)对于每个频繁项集,产生其所有的非空子集。
(2)对于每个非空子集,根据置信度公式进计算置信度,并筛掉不满足设定的最小置信度阈值的项。
(3)循环1~2步骤,直到挖出所有关联规则。
支持度和置信度
公式定义
数据例子
存在以下
a | b | c | d | e |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 0 |
1 | 1 | 1 | 1 | 0 |
1 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 0 |
1 | 1 | 0 | 0 | 0 |
1 | 1 | 1 | 0 | 1 |
1 | 1 | 1 | 0 | 0 |
1 | 0 | 1 | 0 | 1 |
(1)支持度(为例)
,,所以
(2)置信度(为例)
,,所以
基于 Python 实现
Apriori类
class Apriori:
"""
---类名---
Apriori
---数据成员---
MIN_Support: 最小支持度
MIN_Confidence: 最小置信度
K_ItemSet: k项集
K_ItemSupprot: k项集支持度
rules: 规则
---方法---
__init__(): 设置最小支持度和最小置信度(默认为0.5,0.5)
init: 初始化,方便对象生成和调用不在一起
get_candidate_one_set(): 获得候选第一项集
get_k_itemset(): 获得 k 项集
sieve_itmeset(): 筛选项集
get_rules(): 获取规则
one_confidence(): 计算并筛选规则
more_confidence(): 递归规则
display_k_itemset(): 显示 k 项集
display_rules(): 显示规则
run(): 运行入口
"""
# 对象生成初始化
def __init__(self, MIN_Support = 0.5, MIN_Confidence = 0.5):
self.MIN_Support = MIN_Support
self.MIN_Confidence = MIN_Confidence
self.K_ItemSet = []
self.K_ItemSupprot = []
self.rules = []
# 初始化
def init(self):
self.K_ItemSet = []
self.K_ItemSupprot = []
self.rules = []
# 获得候选一项集
def get_candidate_one_set(self, dataSet):
one_set = []
# 遍历添加
for lst in dataSet:
for item in lst:
if not [item] in one_set:
one_set.append([item])
# 排序
one_set.sort()
# 将列表冻结
return list(map(frozenset, one_set))
# 获得 K 项集
def get_k_itemset(self, k_next, K):
k_itemset = [] #K-项集
# 两两组合
for i in range(0,len(k_next)):
for j in range(i+1,len(k_next)):
# 判断前 k-2 项是否相同
L1 = list(k_next[i])[:K-2]
L2 = list(k_next[j])[:K-2]
if L1==L2:
k_itemset.append(k_next[i]|k_next[j])
return k_itemset
# 筛选项集
def sieve_itmeset(self, Data, itmeset):
item_frequency = {}
for item in Data:
for element in itmeset:
if element.issubset(item):
if not element in item_frequency:
item_frequency[element] = 1
else:
item_frequency[element] += 1
numItems = float(len(Data)) #数据集中总的项集个数
sieve_k_itemset = [] #频繁项集
sieve_k_itemSupprot={} #项集中各项支持度
for key in item_frequency:
support = item_frequency[key]/numItems #支持度计算:元素出现次数 / 总项集数
if support>=self.MIN_Support: #满足最小支持度添加到频繁项集列表中
sieve_k_itemset.insert(0, key)
sieve_k_itemSupprot[key] = support
return sieve_k_itemset, sieve_k_itemSupprot
# 运行入口
def run(self, dataSet):
self.init()
# 获取候选一项集
candidate_one_set = self.get_candidate_one_set(dataSet)
# 转换为字典
Data = list(map(set, dataSet))
# 过滤候选一项集
sieve_one_set, self.K_ItemSupprot = self.sieve_itmeset(Data, candidate_one_set)
# k=1的列表
self.K_ItemSet = [[0], sieve_one_set]
# 一直筛选直到小于等于 1 为止。
K = 2
while(len(self.K_ItemSet[K-1]) > 1):
# 从 k-1 中构造候选 k 项集
candidate_k_itemset = self.get_k_itemset(self.K_ItemSet[K-1], K)
# 过滤候选 k 项集,并获取 k 项集支持度
sieve_k_itemset, sieve_k_itemSupprot = self.sieve_itmeset(Data, candidate_k_itemset)
# 更新项集
self.K_ItemSupprot.update(sieve_k_itemSupprot)
self.K_ItemSet.append(sieve_k_itemset)
K += 1
self.get_rules()
# 获取规则
def get_rules(self):
self.rules = []
# 将每一个分项集构造出关系
for i in range(2, len(self.K_ItemSet)):
for k_itemset in self.K_ItemSet[i]:
fz_k_itemset = [frozenset([x]) for x in k_itemset]
#print(fz_k_itemset)
if(i > 2):
self.more_confidence(k_itemset,fz_k_itemset)
else:
self.one_confidence(k_itemset,fz_k_itemset)
# 计算并筛选规则
def one_confidence(self, itemset, fz_k_itemset):
#存储 fz_k_itemset 项中强关联规则
item_realted = []
for item in fz_k_itemset:
# 计算置信度
conf = self.K_ItemSupprot[itemset]/self.K_ItemSupprot[itemset - item]
# 判断是否满足最小置信度
if conf >= self.MIN_Confidence:
self.rules.append((itemset - item, item, conf))
item_realted.append(item)
return item_realted
# 递归规则
def more_confidence(self, itemset, fz_k_itemset):
if (len(itemset) > len(fz_k_itemset[0])+1):
itemset_reunion = self.get_k_itemset(fz_k_itemset, len(fz_k_itemset[0]) + 1)
# 计算置信度并过滤
itemset_reunion_filtered = self.one_confidence(itemset, itemset_reunion)
# 若存在强关联规则,递归组合计算置信度
if(len(itemset_reunion_filtered) > 1):
self.more_confidence(itemset, itemset_reunion_filtered)
# 显示 k 项集
def display_k_itemset(self):
for k_itemset in self.K_ItemSet:
print(k_itemset)
# 显示规则
def display_rules(self):
for rule in self.rules:
print(str(rule[0]) + " ---> " + str(rule[1]) + " Confidence:" + str(rule[2]))
调用
apriori = Apriori(MIN_Support=0.4, MIN_Confidence=0.5)
apriori.run(dataSet)
apriori.display_rules()
apriori.display_k_itemset()
基于 apyori 实现
from apyori import apriori
pd.DataFrame(apriori(transactions=dataSet, min_support=0.5, min_confidence=0.6))
附录(关于数据预处理)
存在一张表,如下:(第一行是列号,忽略)
可以使用下面这个方法将这个
import numpy as np
import pandas as pd
data = pd.read_excel("./menu_orders.xls")
df = pd.DataFrame(list(map(lambda x:pd.Series(1, index = x[pd.notnull(x)]), data.values))).fillna(0)
#df = df[sorted(df.columns)]
dataSet = []
for i in range(0,df.shape[0]):
dataSet.append([x for x in df.columns if df[x][i]])
print(dataSet)
执行结果:
[['b', 'd'], ['b', 'c'], ['a', 'b', 'c', 'd'], ['a', 'b'], ['b', 'c'], ['a', 'b'], ['a', 'b', 'c', 'e'], ['a', 'b', 'c'], ['a', 'c', 'e']]