分解过程如下,完整代码在最后。
不知道apriori算法规则的小伙伴可以看看我写的另一个文章
def load_data_set():
"""
加载一个示例数据集(来自数据挖掘:概念和技术,第3版)
返回:数据集:事务列表。每个事务包含若干项。
"""
data_set = [
['l1', 'l2', 'l5']
, ['l2', 'l4']
, ['l2', 'l3']
, ['l1', 'l2', 'l4']
, ['l1', 'l3']
, ['l2', 'l3']
, ['l1', 'l3']
, ['l1', 'l2', 'l3', 'l5']
, ['l1', 'l2', 'l3']
]
return data_set
def create_C1(data_set):
"""
通过扫描数据集创建频繁的候选1-itemset c1。
参数:
data_set:事务列表。每个事务包含若干项。
返回:
C1:包含所有频繁候选的1-项集的集合
"""
C1 = set()
for t in data_set:
for item in t:
item_set = frozenset([item])
C1.add(item_set)
return C1
if __name__ == "__main__":
data_set = load_data_set()
C1 = create_C1(data_set)
for item in C1:
print(item)
set函数的作用:
set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等
x = set(‘runoob’)
y = set(‘google’)
x, y (set([‘b’, ‘r’, ‘u’, ‘o’, ‘n’]), set([‘e’, ‘o’, ‘g’, ‘l’])) # 重复的被删除
x & y # 交集 set([‘o’])
x | y # 并集 set([‘b’, ‘e’, ‘g’, ‘l’, ‘o’, ‘n’, ‘r’, ‘u’])
x - y # 差集 set([‘r’, ‘b’, ‘u’, ‘n’])
frozenset()函数: 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。
为什么需要冻结的集合(即不可变的集合)呢?因为在集合的关系中,有集合的中的元素是另一个集合的情况,但是普通集合(set)本身是可变的,那么它的实例就不能放在另一个集合中(set中的元素必须是不可变类型)。
所以,frozenset提供了不可变的集合的功能,当集合不可变时,它就满足了作为集合中的元素的要求,就可以放在另一个集合中了。
输出结果
PS D:\Program Files\Anaconda\workplaces> cd 'd:\Program Files\Anaconda\workplaces'; & 'D:\Program Files\Anaconda\python.exe' 'c:\Users\laowu\.vscode\extensions\ms-python.python-2020.9.114305\pythonFiles\lib\python\debugpy\launcher' '49700' '--' 'd:\Program Files\Anaconda\workplaces\test.py'
frozenset({'l3'})
frozenset({'l4'})
frozenset({'l5'})
frozenset({'l2'})
frozenset({'l1'})
在代码中增加以下函数
def is_apriori(Ck_item, Lksub1):
"""
判断一个频繁候选的k项集是否满足Apriori性质。
参数:
Ck_item:Ck中包含所有频繁候选k项集的频繁候选k项集。
Lksub1: Lk-1,一个包含所有频繁候选(k-1)项集的集合。
返回:
真:满足先验性质。
假:不满足先验性质。
"""
for item in Ck_item:
sub_Ck = Ck_item - frozenset([item])
if sub_Ck not in Lksub1:
return False
return True
def create_Ck(Lksub1, k):
"""
通过Lk-1自己的连接操作创建包含所有频繁候选k-itemset的集合ck。
参数:
Lksub1: Lk-1,一个包含所有频繁候选(k-1)项集的集合。
k:频繁项目集的项目编号。
返回:Ck:包含所有频繁候选k项集的集合。
"""
Ck = set()
len_Lksub1 = len(Lksub1)
list_Lksub1 = list(Lksub1)
for i in range(len_Lksub1):
for j in range(1, len_Lksub1):
l1 = list(list_Lksub1[i])
l2 = list(list_Lksub1[j])
l1.sort()
l2.sort()
if l1[0:k-2] == l2[0:k-2]:
Ck_item = list_Lksub1[i] | list_Lksub1[j]
# pruning
if is_apriori(Ck_item, Lksub1):
Ck.add(Ck_item)
return Ck
def generate_Lk_by_Ck(data_set, Ck, min_support, support_data):
"""
通过从ck执行删除策略生成Lk。
参数:
data_set:事务列表。每个事务包含若干项。
ck:包含所有频繁候选k项集的集合。
min_support:最小支持。
support_data:字典。关键是频繁项集,值是支持。
返回:
Lk:一个包含所有常见k项集的集合。
"""
Lk = set()
item_count = {}
for t in data_set:
for item in Ck:
if item.issubset(t):
if item not in item_count:
item_count[item] = 1
else:
item_count[item] += 1
t_num = float(len(data_set))
for item in item_count:
if (item_count[item] / t_num) >= min_support:
Lk.add(item)
support_data[item] = item_count[item] / t_num
return Lk
def generate_L(data_set, k, min_support):
"""
生成所有频繁项集。
参数:
data_set:事务列表。每个事务包含若干项。
k:所有频繁项集的最大项数。
min_support:最小支持。
返回:
L: Lk的清单
support_data:字典。关键是频繁项集,值是支持。
"""
support_data = {}
C1 = create_C1(data_set)
L1 = generate_Lk_by_Ck(data_set, C1, min_support, support_data)
Lksub1 = L1.copy()
L = []
L.append(Lksub1)
for i in range(2, k+1):
Ci = create_Ck(Lksub1, i)
Li = generate_Lk_by_Ck(data_set, Ci, min_support, support_data)
Lksub1 = Li.copy()
L.append(Lksub1)
return L, support_data
if __name__ == "__main__":
data_set = load_data_set()
C1 = create_C1(data_set)
print("请输入最大频繁项:")
n=int(input())
L, support_data = generate_L(data_set, n, 0.2)
for item in support_data:
print(item, ": ", support_data[item])
issubset函数作用:判断是否在集合中
输出结果
PS D:\Program Files\Anaconda\workplaces> cd 'd:\Program Files\Anaconda\workplaces'; & 'D:\Program Files\Anaconda\python.exe' 'c:\Users\laowu\.vscode\extensions\ms-python.python-2020.9.114305\pythonFiles\lib\python\debugpy\launcher' '51052' '--' 'd:\Program Files\Anaconda\workplaces\test.py'
请输入最大频繁项:
5
frozenset({'l1'}) : 0.6666666666666666
frozenset({'l2'}) : 0.7777777777777778
frozenset({'l5'}) : 0.2222222222222222
frozenset({'l4'}) : 0.2222222222222222
frozenset({'l3'}) : 0.6666666666666666
frozenset({'l1', 'l2'}) : 0.4444444444444444
frozenset({'l1', 'l5'}) : 0.2222222222222222
frozenset({'l5', 'l2'}) : 0.2222222222222222
frozenset({'l4', 'l2'}) : 0.2222222222222222
frozenset({'l3', 'l2'}) : 0.4444444444444444
frozenset({'l1', 'l3'}) : 0.4444444444444444
frozenset({'l1', 'l5', 'l2'}) : 0.2222222222222222
frozenset({'l1', 'l3', 'l2'}) : 0.2222222222222222
最大频繁项集为3,则4,5为空。
在代码中增加以下函数
def generate_big_rules(L, support_data, min_conf):
"""
从频繁的项目集生成大规则。
参数:
L: Lk的清单。
support_data:一本字典。关键是频繁项集,值是支持。
min_conf:最小信任
返回:
大规则列表:包含所有大规则的列表。每个大的规则都被表现出来作为一个r3。
"""
big_rule_list = []
sub_set_list = []
for i in range(0, len(L)):
for freq_set in L[i]:
for sub_set in sub_set_list:
if sub_set.issubset(freq_set):
conf = support_data[freq_set] / support_data[freq_set - sub_set]
big_rule = (freq_set - sub_set, sub_set, conf)
if conf >= min_conf and big_rule not in big_rule_list:
# print freq_set-sub_set, " => ", sub_set, "conf: ", conf
big_rule_list.append(big_rule)
sub_set_list.append(freq_set)
return big_rule_list
if __name__ == "__main__":
data_set = load_data_set()
C1 = create_C1(data_set)
print("请输入最大频繁项:")
n=int(input())
L, support_data = generate_L(data_set, n, 0.2)
rule_list = generate_big_rules(L, support_data, 0.7)
for item in rule_list:
print(item[0], "=>", item[1], "'s conf:", item[2])
输出结果
frozenset({'l5'}) => frozenset({'l2'}) 's conf: 1.0
frozenset({'l4'}) => frozenset({'l2'}) 's conf: 1.0
frozenset({'l5'}) => frozenset({'l1'}) 's conf: 1.0
frozenset({'l1', 'l5'}) => frozenset({'l2'}) 's conf: 1.0
frozenset({'l5', 'l2'}) => frozenset({'l1'}) 's conf: 1.0
frozenset({'l5'}) => frozenset({'l1', 'l2'}) 's conf: 1.0
完整代码
def load_data_set():
"""
加载一个示例数据集(来自数据挖掘:概念和技术,第3版)
返回:数据集:事务列表。每个事务包含若干项。
"""
data_set = [
['l1', 'l2', 'l5']
, ['l2', 'l4']
, ['l2', 'l3']
, ['l1', 'l2', 'l4']
, ['l1', 'l3']
, ['l2', 'l3']
, ['l1', 'l3']
, ['l1', 'l2', 'l3', 'l5']
, ['l1', 'l2', 'l3']
]
return data_set
def create_C1(data_set):
"""
通过扫描数据集创建频繁的候选1-itemset c1。
参数:
data_set:事务列表。每个事务包含若干项。
返回:
C1:包含所有频繁候选的1-项集的集合
"""
C1 = set()
for t in data_set:
for item in t:
item_set = frozenset([item])
C1.add(item_set)
return C1
def is_apriori(Ck_item, Lksub1):
"""
判断一个频繁候选的k项集是否满足Apriori性质。
参数:
Ck_item:Ck中包含所有频繁候选k项集的频繁候选k项集。
Lksub1: Lk-1,一个包含所有频繁候选(k-1)项集的集合。
返回:
真:满足先验性质。
假:不满足先验性质。
"""
for item in Ck_item:
sub_Ck = Ck_item - frozenset([item])
if sub_Ck not in Lksub1:
return False
return True
def create_Ck(Lksub1, k):
"""
通过Lk-1自己的连接操作创建包含所有频繁候选k-itemset的集合ck。
参数:
Lksub1: Lk-1,一个包含所有频繁候选(k-1)项集的集合。
k:频繁项目集的项目编号。
返回:Ck:包含所有频繁候选k项集的集合。
"""
Ck = set()
len_Lksub1 = len(Lksub1)
list_Lksub1 = list(Lksub1)
for i in range(len_Lksub1):
for j in range(1, len_Lksub1):
l1 = list(list_Lksub1[i])
l2 = list(list_Lksub1[j])
l1.sort()
l2.sort()
if l1[0:k-2] == l2[0:k-2]:
Ck_item = list_Lksub1[i] | list_Lksub1[j]
# pruning
if is_apriori(Ck_item, Lksub1):
Ck.add(Ck_item)
return Ck
def generate_Lk_by_Ck(data_set, Ck, min_support, support_data):
"""
通过从ck执行删除策略生成Lk。
参数:
data_set:事务列表。每个事务包含若干项。
ck:包含所有频繁候选k项集的集合。
min_support:最小支持。
support_data:字典。关键是频繁项集,值是支持。
返回:
Lk:一个包含所有常见k项集的集合。
"""
Lk = set()
item_count = {}
for t in data_set:
for item in Ck:
if item.issubset(t):
if item not in item_count:
item_count[item] = 1
else:
item_count[item] += 1
t_num = float(len(data_set))
for item in item_count:
if (item_count[item] / t_num) >= min_support:
Lk.add(item)
support_data[item] = item_count[item] / t_num
return Lk
def generate_L(data_set, k, min_support):
"""
生成所有频繁项集。
参数:
data_set:事务列表。每个事务包含若干项。
k:所有频繁项集的最大项数。
min_support:最小支持。
返回:
L: Lk的清单
support_data:字典。关键是频繁项集,值是支持。
"""
support_data = {}
C1 = create_C1(data_set)
L1 = generate_Lk_by_Ck(data_set, C1, min_support, support_data)
Lksub1 = L1.copy()
L = []
L.append(Lksub1)
for i in range(2, k+1):
Ci = create_Ck(Lksub1, i)
Li = generate_Lk_by_Ck(data_set, Ci, min_support, support_data)
Lksub1 = Li.copy()
L.append(Lksub1)
return L, support_data
def generate_big_rules(L, support_data, min_conf):
"""
从频繁的项目集生成大规则。
参数:
L: Lk的清单。
support_data:一本字典。关键是频繁项集,值是支持。
min_conf:最小信任
返回:
大规则列表:包含所有大规则的列表。每个大的规则都被表现出来作为一个r3。
"""
big_rule_list = []
sub_set_list = []
for i in range(0, len(L)):
for freq_set in L[i]:
for sub_set in sub_set_list:
if sub_set.issubset(freq_set):
conf = support_data[freq_set] / support_data[freq_set - sub_set]
big_rule = (freq_set - sub_set, sub_set, conf)
if conf >= min_conf and big_rule not in big_rule_list:
# print freq_set-sub_set, " => ", sub_set, "conf: ", conf
big_rule_list.append(big_rule)
sub_set_list.append(freq_set)
return big_rule_list
if __name__ == "__main__":
data_set = load_data_set()
L, support_data = generate_L(data_set, k=3, min_support=0.2)
big_rules_list = generate_big_rules(L, support_data, min_conf=0.7)
for Lk in L:
print("="*50)
print("frequent " + str(len(list(Lk)[0])) + "-itemsets\t\tsupport")
print("="*50)
for freq_set in Lk:
print(freq_set, support_data[freq_set])
print
print("关联规则:")
for item in big_rules_list:
print(item[0], "=>", item[1], "conf: ", item[2])