原文笔记
组织完整的 Apriori 算法
当前一个数项(k-1)的集合中项的个数大于0时
构建一个k个项组成的候选项集的列表
检查数据以确认每个项集都是频繁的
保留频繁项集并构建k+1项组成的候选项集的列表
算法使用(部分算法如scanD见上一篇)
dataSet=loadDataSet();
//dataSet: [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] //
L, supportData=apriori(dataSet);
//L:最终满足支持度的全部组合项 [[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})], [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})], [frozenset({2, 3, 5})], []] supportData:大部分记录的支持度记录 {frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75, frozenset({1, 3}): 0.5, frozenset({2, 5}): 0.75, frozenset({3, 5}): 0.5, frozenset({2, 3}): 0.5, frozenset({1, 5}): 0.25, frozenset({1, 2}): 0.25, frozenset({2, 3, 5}): 0.5} //
retList=aprioriGen(L[0],2);
//retList:一项数字生成的两项的组合 [frozenset({2, 5}), frozenset({3, 5}), frozenset({1, 5}), frozenset({2, 3}), frozenset({1, 2}), frozenset({1, 3})] //
算法流程
#total apriori def aprioriGen(Lk, k): #组合,向上合并
//Lk:数字项的集合 [frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})] k:与项集元素个数 k 2 //
#creates Ck 参数:频繁项集列表 Lk 与项集元素个数 k
retList = []
lenLk = len(Lk)
//lenLk:数字项的集合的长度 4 //
for i in range(lenLk):
//i:循环数字项的集合 0 //
for j in range(i+1, lenLk): #两两组合遍历
//j:往后依次获取数字项的组合 1 //
L1 = list(Lk[i])[:k-2]; L2 = list(Lk[j])[:k-2]
//L1:Lk[i]的前k-2项 L2:Lk[j]的前k-2项 k:2 //
L1.sort(); L2.sort()
//排序便于下面比较 //
if L1==L2:
retList.append(Lk[i] | Lk[j]) #set union
//#若两个集合的前k-2个项相同时,则将两个集合合并 //
return retList
#apriori
def apriori(dataSet, minSupport = 0.5):
//dataSet:点集 [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] minSupport:最小支持度 //
C1 = createC1(dataSet)
//C1:dataSet最小 [frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})] //
D = list(map(set, dataSet)) #python3
//D:dataSet list map化?好像没有必要直接使用dataSet也是可以求scanD [{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}] //
L1, supportData = scanD(D, C1, minSupport)#单项最小支持度判断 0.5,生成L1
//L1:满足0.5的点集 [frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})] supportData:所有单数字的支持度 {frozenset({1}): 0.5, frozenset({3}): 0.75, frozenset({4}): 0.25, frozenset({2}): 0.75, frozenset({5}): 0.75} //
L = [L1]
//L:记录全部的频繁项,包含组合 [[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]] //
k = 2
//组合个数的起点 //
while (len(L[k-2]) > 0):#创建包含更大项集的更大列表,直到下一个大的项集为空
//前一项数字个数的列表不为空时循环//
Ck = aprioriGen(L[k-2], k)#Ck
//使用前一个数字组合生成多一个数的数字组合:注(算法优化其实目前k直接是L[k-2]单个项的长度+1) Ck: [frozenset({2, 5}), frozenset({3, 5}), frozenset({1, 5}), frozenset({2, 3}), frozenset({1, 2}), frozenset({1, 3})] //
Lk, supK = scanD(D, Ck, minSupport)#get Lk
//Ck中满足支持度的点集和支持度情况 Lk:[frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})] supK:{frozenset({1, 3}): 0.5, frozenset({2, 5}): 0.75, frozenset({3, 5}): 0.5, frozenset({2, 3}): 0.5, frozenset({1, 5}): 0.25, frozenset({1, 2}): 0.25} //
supportData.update(supK)
//支持度存入 //
L.append(Lk)
//满足支持度的点组合存入 //
k += 1
//#继续向上合并 生成项集个数更多的 //
return L, supportData
//最终的频繁项和全部组合的支持度 //