赞
踩
Apriori算法是经典的挖掘频繁项目集和关联规则的数据挖掘算法。当定义问题时,通常会使用先验知识或者假设,这被称作"一个先验"。算法使用频繁项目集的先验性质,即频繁项目集的所有非空子集也一定是频繁的。Apriori算法使用一种称为逐层搜索的迭代方法,其中k项集用于探索(k+1)项集。首先通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合。该集合记为L1。然后,使用L1找出频繁2项集的集合L2,使用L2找出L3……如此下去,直到不能再找到频繁k项集。每找出一个Lk需要一次数据库的完整扫描。Apriori算法利用频繁项目集的先验性质来压缩搜索空间。
项目空间集理论:
定理1:若项目集X是频繁项目集,则它的所有非空子集都是频繁项目集。
定理2:如项目集X是非频繁项目集,则它的所有超集都是非频繁项目集。
红色部分为不小于最小支持度的项,被添加到频繁项目集中;
黄色部分为小于最小支持度的项,它及它的超集不会添加到频繁项目集中;
蓝色部分为最大频繁项目集,本身是频繁项集,且其中任何一项的超集都是非频繁的。
- import itertools
-
-
- def loadData():
- try:
- with open("Apriori.txt", "r") as f:
- data = []
- for line in f:
- data.append(line.strip().split(','))
- return data
- except Exception as e:
- print(e)
-
-
- # 利用set的性质将交易记录中的元素去重,从而得到构成交易记录的元素集合
- def data_index(data_set):
- items = set(itertools.chain(*data_set))
- # 建立字符串与编号之间的相互映射
- str_index = {}
- index_str = {}
-
- # 打印元素与编号的对应关系,后续操作对元素编号进行处理
- print("------------------------------元素编号------------------------------")
- for index, item in enumerate(items):
- print(index, '->', item)
- str_index[item] = index
- index_str[index] = item
-
- # 原字符串转换为index
- for i in range(len(data_set)):
- for j in range(len(data_set[i])):
- data_set[i][j] = str_index[data_set[i][j]]
-
- return data_set, index_str
-
-
- # 根据支持数筛选频繁项目集
- def Ck_Lk(data_set, Ck, min_support):
- global item
- support = {}
- # 用数据集的每一行跟候选项目集的每个项对比,若该项目集是其中的子集,则自增1,否则为0
- for row in data_set:
- for item in Ck:
- # 判断集合item是否为集合row的子集
- if item.issubset(row):
- # key -- 字典中要查找的键
- # value -- 可选,如果指定键的值不存在时,返回该默认值
- support[item] = support.get(item, 0) + 1
- # k-频繁项目集输出
- print('L{}:{}'.format(len(item), support))
- # 计算频率需要用到长度
- length = len(data_set)
- Lk = {}
- for key, value in support.items():
- sup = value / length
- # 频率大于最小支持度才能进入频繁项目集
- if sup >= min_support:
- Lk[key] = sup
-
- return Lk
-
-
- def Lk_Ck_plus1(Lk):
- Lk_list = list(Lk)
- # 保存组合后的k+1项集
- Ck_plus1 = set()
- Lk_size = len(Lk)
- if Lk_size > 1:
- # 获取频繁项集的长度
- k = len(Lk_list[0])
- for i, j in itertools.combinations(range(Lk_size), 2):
- t = Lk_list[i] | Lk_list[j]
- if len(t) == k + 1:
- Ck_plus1.add(t)
-
- return Ck_plus1
-
-
- def get_all_L(data_set, min_support):
- print("---------------------------候选项目集生成----------------------------")
- # 首先创建候选1项集
- # 把data_set中的元素(已转化为index)去重
- items = set(itertools.chain(*data_set))
- # 用frozenset把项集装进新列表里
- C1 = [frozenset(i) for i in enumerate(items)]
- # 从1-候选项集目到1-频繁项目集(第一次生成频繁项目集不需要对元素进行两两组合)
- L1 = Ck_Lk(data_set, Ck=C1, min_support=min_support)
- L = L1
- Lk = L1
-
- while len(Lk) > 0:
- lk_key_list = list(Lk.keys())
- # k-频繁项目集 到 k+1-候选项目集 进行了两两组合
- Ck_plus1 = Lk_Ck_plus1(lk_key_list)
- # k-候选项目集 到 k-频繁项目集
- Lk = Ck_Lk(data_set, Ck_plus1, min_support)
- if len(Lk) > 0:
- # 把字典Lk的键值对更新到L
- L.update(Lk)
- else:
- break
-
- return L
-
-
- # 关联规则左侧表达式
- def rules_from_item(item):
- left = []
- for i in range(1, len(item)):
- left.extend(itertools.combinations(item, i))
- # difference()方法返回集合的差集
- ans = [(frozenset(i), frozenset(item.difference(i))) for i in left]
-
- return ans
-
-
- # 保存所有候选的关联规则
- def rules_from_L(L, min_confidence):
- rules = []
- for Lk in L:
- # 首先频繁项目集长度需要大于1才能生成关联规则
- if len(Lk) > 1:
- # 在列表末尾一次性追加另一个序列中的多个值
- rules.extend(rules_from_item(Lk))
- result = []
-
- for left, right in rules:
- # left和right都是frozenset类型,二者可以取并集(分子 Ik),然后L里去查询支持度
- support = L[left | right]
- # 置信度公式
- confidence = support / L[left]
- if confidence >= min_confidence:
- result.append({"left": left, "right": right, "support": support, "confidence": confidence})
-
- return result
-
-
- # 关联规则的左表达式和右表达式获取
- def return_str(index_str, result):
- for item in result:
- true_left = []
- true_right = []
- left = list(item['left'])
- for tem in left:
- true_left.append(index_str[tem])
- right = list(item['right'])
- for tem in right:
- true_right.append(index_str[tem])
- item['left'] = frozenset(true_left)
- item['right'] = frozenset(true_right)
- return result
-
-
- # 打印集合
- def print_frozenset(fs):
- ans = ''
- for i in fs:
- ans += i
- return ans
-
-
- def main():
- # 加载数据
- data_set = loadData()
- # 设置参数
- min_support = 0.5
- min_confidence = 0.5
- print("-------------------------导入事务数据库数据--------------------------")
- for i in range(0, len(data_set)):
- print(data_set[i])
- # 把数据转为数字(便于计算)
- data_set, index_str = data_index(data_set)
- # 生成频繁项目集
- L = get_all_L(data_set, min_support=min_support)
- # 生成关联规则
- result = rules_from_L(L, min_confidence=min_confidence)
- result = return_str(index_str, result)
-
- print("-----------------------------关联规则生成------------------------------")
- print("\t\t", " min_support:", min_support, "\t\t\t\t", "min_confidence:", min_confidence)
- print("---------------------------------------------------------------------")
- print("", "No.", "\t\t", "Lk", "\t", "Xm-1", "\t\t", "Confidence", "\t", "Support", "\t\t", "Rule")
- index = 1
- for item in result:
- print("", str(index).zfill(3), "\t\t", print_frozenset(item["left"] | item["right"]), "\t ",
- print_frozenset(item["left"]), "\t\t ",
- round(item["confidence"] * 100), "%\t\t ",
- round(item["support"] * 100), "%\t\t ",
- print_frozenset(item["left"]), "->", print_frozenset(item["right"]))
- index += 1
-
-
- if __name__ == "__main__":
- main()
- a,c,d,e,f,g
- a,b,c,d,e,h
- a,b,c,d,e,f,g,h
- a,b,c,g,h
- a,b,c,d,g,h
- a,b,c,d,e,f,g,h
- a,b,c,d,e,f,g
- a,b,c,e,g,h
- a,b,c,d,e,f,h
- c,d,e,f,g,h
- a,b,c,d,g,h
- a,c,d,e,f,g,h
- a,b,c,e,f,g,h
- b,c,e,f,g,h
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。