学习挖掘频繁项集,掌握apriori算法
1.实现用apriori算法挖掘频繁项集(最小支持度计数2)
2.分析你所实现的apriori算法的缺点
3. 数据集:
TID | 项集 |
---|---|
T100 | I1,I2,I5 |
T200 | I2,I4 |
T300 | I2,I3 |
T400 | I1,I2,I4 |
T500 | I1,I3 |
T600 | I2,I3 |
T700 | I1,I3 |
T800 | I1,I2,I3,I5 |
T900 | I1,I2,I3 |
# 录入数据
def data_fetch():
data = [['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
# 根据项目,寻找支持度计数
def xunzhao(s, L):
k = len(s) - 1 # 根据项目长度,决定在频繁几项集中寻找
if k < 0: # s为空的情况
print(s, '不是有效输入')
# 标志变量,如果s中的项目有和当前比较的不同的,就置0;
t = 0
for i in range(len(L[k])): # 遍历频繁k项集
t = 1
for j in range(k + 1): # 开始比较是不是该项目
if L[k][i][0][j] != s[j]:
t = 0
break
if t:
return L[k][i][1] # 是的话,返回该项目的支持度计数
print('未找到') # 遍历结束的话说明未找到
return -1 # 返回 -1 (无)
# 得到划分,并顺便求出置信度
def huafen(L, l, conf): # 划分得到置信度
X = l[0] # 需要划分的列表
lx = len(X) # 长度
# 用二进制的性质求真子集
for i in range(1, 2 ** lx - 1):
s1 = []
s2 = []
for j in range(lx):
# 二进制末尾是0就进s1,否则就进s2达到划分目的
if (i >> j) % 2:
s1.append(X[j])
else:
s2.append(X[j])
conf[str(s1), '->', str(s2)] = l[1] / xunzhao(s1, L)
# 判断s中的数据在data中的数目
def jishu(s, data):
c = 0 # 记录出现数目
# 标志变量,如果s中的数据有在data这一行不存在的,就置0;
t = 0
for ii in data: # 数据每一行
t = 1
for jj in s: # 对于 s 中的每一个项
if not (jj in ii):
t = 0
break
c += t # 如果 s 在这一行存在,c++
return c
# 输入频繁k-1项集,支持度计数,数据,输出频繁k项集
def Apriori(L, N, data):
if not L:
return L
L_ = [] # 频繁k项集
L = [i[0] for i in L] # k-1项集包含哪些
k = len(L[0]) + 1 # 几项集
L_len = len(L)
up = k - 2 # 拼接同项长度
i = 0
while i < L_len - 1: # 只剩最后一个时肯定没法拼
A = L[i][0:up] # 拼接前项
c = i # 记录走到那个前项了
i += 1 # i 到下一个
for j in range(c + 1, L_len):
if L[j][0:up] != A: # 前几项不一致就停止
i = j # i 快进到发现新键值的地方
break
else: # 前几项一致时
s = L[c] + L[j][up:] # 生成预选项
t = jishu(s, data) # 得到 s 的支持度计数
if t >= N: # 支持度计数大于N
L_.append([s, t]) # 添加到频繁项集中
return L_
data = data_fetch() # 生成数据,存到data
N = 2 # 支持度计数
L = {} # 储存一项集
for i in data: # 得到所有的一项集
for j in i:
if j in L:
L[j] += 1
else:
L[j] = 1
L_1 = [] # 储存频繁一项集
for i in L.keys(): # 取其中所有的频繁集
if L[i] >= N:
L_1.append([[i], L[i]])
L = [] # 频繁1~4项集
L.append(sorted(L_1, key=lambda x: x[0])) # 按键值排序转为列表
print('频繁 1 项集', L[0])
for i in range(3):
L.append(Apriori(L[i], N, data)) # 求频繁2项集
print('频繁', i + 2, '项集', L[i + 1])
# 置信度计算 ===============================================
conf = {} # 储存置信度
# 对每一个k项集分析
print('置信度:============================================')
for i in L[1:len(L)]: # 频繁1项集不用看
for j in i:
huafen(L, j, conf) # 划分得到置信度
for key in conf:
print(key,conf[key]*100,'%')
频繁 1 项集 [[['l1'], 6], [['l2'], 7], [['l3'], 6], [['l4'], 2], [['l5'], 2]]
频繁 2 项集 [[['l1', 'l2'], 4], [['l1', 'l3'], 4], [['l1', 'l5'], 2], [['l2', 'l3'], 4], [['l2', 'l4'], 2], [['l2', 'l5'], 2]]
频繁 3 项集 [[['l1', 'l2', 'l3'], 2], [['l1', 'l2', 'l5'], 2]]
频繁 4 项集 []
置信度:============================================
("['l1']", '->', "['l2']") 66.66666666666666 %
("['l2']", '->', "['l1']") 57.14285714285714 %
("['l1']", '->', "['l3']") 66.66666666666666 %
("['l3']", '->', "['l1']") 66.66666666666666 %
("['l1']", '->', "['l5']") 33.33333333333333 %
("['l5']", '->', "['l1']") 100.0 %
("['l2']", '->', "['l3']") 57.14285714285714 %
("['l3']", '->', "['l2']") 66.66666666666666 %
("['l2']", '->', "['l4']") 28.57142857142857 %
("['l4']", '->', "['l2']") 100.0 %
("['l2']", '->', "['l5']") 28.57142857142857 %
("['l5']", '->', "['l2']") 100.0 %
("['l1']", '->', "['l2', 'l3']") 33.33333333333333 %
("['l2']", '->', "['l1', 'l3']") 28.57142857142857 %
("['l1', 'l2']", '->', "['l3']") 50.0 %
("['l3']", '->', "['l1', 'l2']") 33.33333333333333 %
("['l1', 'l3']", '->', "['l2']") 50.0 %
("['l2', 'l3']", '->', "['l1']") 50.0 %
("['l1']", '->', "['l2', 'l5']") 33.33333333333333 %
("['l2']", '->', "['l1', 'l5']") 28.57142857142857 %
("['l1', 'l2']", '->', "['l5']") 50.0 %
("['l5']", '->', "['l1', 'l2']") 100.0 %
("['l1', 'l5']", '->', "['l2']") 100.0 %
("['l2', 'l5']", '->', "['l1']") 100.0 %
进程已结束,退出代码为 0
生成备选频繁项集时,没有充分利用频繁项集的子集也属于频繁项集的性质,导致有一些冗余。