当前位置:   article > 正文

关联规则分析(频繁项集查找方法为apriori方法的Fk-1*Fk-1)_fk-1×fk-1生成候选项集的过程

fk-1×fk-1生成候选项集的过程

关联分析思想因其在生活中的某些方面(比如购物推荐)能够取得良好的效果,所以在机器学习里面占有一席之地,如今随着大数据时代的到来,找出数据之间的关系显得更加重要,这次,通过一个小例子来探究一下关联分析背后的秘密。

一:实验要求: 

实验目的

1. 理解频繁项集、关联规则等基本概念

2. 运用Apriori算法分析数据中频繁项集和关联规则

实验问题描述

  1. 编写Apriori算法,分析出下表中数据集的频繁项集和关联规则,最小支持度为30%,最小置信度为50%
  2. 讨论不同参数(最小支持度、最小置信度)对实验结果的影响。

实验要求

  1. 关联分析基本算法需要编程实现,不能直接调用第三方函数库
  2. 程序可以运行,输出结果

实验报告内容

1. 实验内容:

2. 设计思想:主要算法的基本思想。

3. 主要算法的程序实现

4. 调试报告:调试过程中遇到的主要问题是如何解决的;对设计和编码的回顾讨论和分析以及对主要算法的改进设想。

5. 实验总结:对实验用到的理论知识的理解,在算法设计上有何创新。

实验报告提交要求

1. 实验报告应使用学校统一给定的实验报告的封面,实验名称为实验指导书中的实验名称。

2. 实验报告提交内容包括:1)实验报告的word版;2)程序源代码(单独放在一个文件夹内)。将上述2部分内容放在一个文件夹内。命名格式:班级-学号-姓名

3.实验完成后一周内在课堂派上提交直接上传原始文件不要压缩)。

二:解决思路

代码:

  1. """
  2. coding:utf-8
  3. @author: Li Sentan
  4. @time:2021.11.02
  5. @file:guanliansys.py
  6. """
  7. import itertools
  8. def delsame(B,L):#B,L均为字符串,返回值是在B中删除两个字符串中的相同字符后的字符串
  9. b = sorted(B)
  10. c = b
  11. l = sorted(L)
  12. for i in l:
  13. for j in b:
  14. if i == j:
  15. c.remove(i)
  16. d = "".join(sorted(c))
  17. return d
  18. def listtoset(m):#将二维列表转化为集合的列表
  19. a = []
  20. for i in range(len(m)):
  21. c = set()
  22. for j in range(len(m[i])):
  23. c.add(m[i][j])
  24. a.append(c)
  25. return a
  26. #定义一个关联分析的类
  27. class assys():
  28. def __init__(self,dataset,m = 1,minsupport = 0.5):
  29. self.a = listtoset(dataset)
  30. self.dataset = dataset
  31. self.m = m
  32. self.minsupport = minsupport
  33. self.Ck = dict()
  34. self.mincon = 0
  35. def createC1(self):#创造1-项集
  36. Cp1 = {}
  37. for transaction in self.dataset:
  38. for item in transaction:
  39. if item not in Cp1:
  40. Cp1[item] = 0
  41. Cp1[item] += 1
  42. return Cp1
  43. def supportset(self, Cp1):#选出1-频繁项集
  44. lk = []
  45. C1 = dict()
  46. for key in Cp1:
  47. support = Cp1[key] / len(self.dataset)
  48. if support >= self.minsupport:
  49. lk.append(key)
  50. C1[key] = support
  51. return lk, C1
  52. def aprioriGen(self,Lk, k):#用Fk-1*Fk-1选出K-频繁项集并以字典的形式存储频繁项集的支持度。
  53. lk = []
  54. Cpk = dict()
  55. for i in range(len(Lk)):
  56. for j in range(i+1,len(Lk)):
  57. L1 = Lk[i][:k - 2]
  58. L2 = Lk[j][:k - 2]
  59. if L1 == L2:
  60. c = Lk[i][:k - 1]+Lk[j][k-2]
  61. b = set(sorted(c))
  62. if c not in Cpk:
  63. Cpk[c] = 0
  64. for m in self.a:
  65. if b.issubset(m):
  66. Cpk[c] += 1
  67. support = Cpk[c]/len(self.dataset)
  68. if support >= self.minsupport:
  69. self.Ck[c] = support
  70. lk.append(c)
  71. return lk
  72. def apriori(self): #构造1-K频繁项集的结构函数,返回值是频繁项集的二维列表和带有支持度信息的字典
  73. Cp1 = self.createC1()
  74. L1,C1 = self.supportset(Cp1)
  75. self.Ck = C1
  76. L = [sorted(L1)]
  77. k = 2
  78. while (k<=self.m and len(L[k - 2]) > 0):
  79. lk = self.aprioriGen(L[k - 2], k)
  80. L.append(lk)
  81. k += 1
  82. if L[-1] == []:
  83. L = L[:-1]
  84. return L,self.Ck
  85. def culcon(self,L,mincon):#选择关联项的函数
  86. o = dict()
  87. if len(L) >= 2:
  88. for i in range(len(L)-1,0,-1):
  89. for j in range(len(L[i])-1,-1,-1):
  90. m = sorted(L[i][j])
  91. for q in range(1, len(m)):
  92. for x in itertools.combinations(m, q):#以元组的形式返回m(为数组)中所有长度为q的子序列,所以下面用.join()方法时要加list()
  93. result = "".join(list(x))
  94. w = L[i][j]
  95. a = result
  96. b = delsame(w,a)
  97. con = self.Ck[w]/self.Ck[a]
  98. if con >=mincon:
  99. o[a + "--->" + b] = round(con,2)
  100. g = sorted(b)
  101. for f in range(1, len(g)):
  102. for h in itertools.combinations(g, f):
  103. result2 = "".join(list(h))
  104. con2 = self.Ck["".join(sorted(result2+a))] / self.Ck[a]
  105. o[a + "--->" + "".join(sorted(result2))] = round(con2,2)
  106. return o
  107. if __name__ == '__main__':
  108. b = [["a", "b", "d", "e"], ["b", "c", "d"], ["a", "b", "d", "e"], ["a", "c", "d", "e"], ["b", "c", "d", "e"],
  109. ["b", "d", "e"], ["c", "d"], ["a", "b", "c"], ["a", "d", "e"], ["b", "d"]]
  110. minsupport = eval(input("请输入最小支持度:"))
  111. M = eval(input("请输入M的值:(0代表输出K-频繁项集,否则代表默认输出1到K-频繁项集)"))
  112. k = eval(input("请输入k的值,得到相应的频繁项集:"))
  113. c = assys(b,k,minsupport)
  114. L,Ck = c.apriori()
  115. if M==0:
  116. try:
  117. print("{",end="")
  118. for key in L[k-1]:
  119. print("{}:{}".format(key,Ck[key]),end=" ")
  120. print("}")
  121. except:
  122. print("没有该频繁项集。")
  123. else:
  124. print(Ck)
  125. mincon = eval(input("请输最小关联度:"))
  126. n = c.culcon(L,mincon)
  127. for key,value in n.items():
  128. print("{}:{}".format(key,value))

如果直接看代码的话还是有些难度的,不过咱们先来分析分析解决思路:

1.我们想要能够找到其中的1-K频繁项集,所以我们从1-频繁项集开始找,一直到K-频繁项集。好的,那我们给定一个最小支持度,根据支持度先把1-频繁项集找出来,再在1-频繁项集的基础上根据Fk-1*Fk-1原则逐次把2,3.....K-频繁项集找出来。

2.我们想要得到所有的关联项,只需要知道图中圈起来的公式来计算置信度: 由公式延伸得知:若X-->AB,则必有:X-->A,X-->B,由于置信度是建立在频繁项集的基础上,所以我们只在所有的频繁项集上寻找满足置信度的关联项。我们先从k-频繁项集出发,将k-频繁项集分成两部分,且两部分都不为空,共有(2的K次方-2)种分配方式。计算第一部分与第二部分的关联置信度,再根据公式延伸得到的规则,若X-->ABC,则X-->ABC的所有真子集,重复上述过程直至2-频繁项集,最终即可得到2-K频繁项集内的所有关联项。

理清了思路,代码实现就简单便捷了。

culcon()方法之前的apriori()是为了得到1-K的频繁项集,在apriori()中调用了aprioriGen(self,Lk, k),aprioriGen(self,Lk, k)是为了寻找K-频繁项集,最后将频繁项集和支持度存在一个字典Ck中,同时L是一个二维列表,每个频繁项集是其中的一个列表。并且频繁项集以字符串的形式表示。笔者在实现过程中用到很多次字符串,列表,集合的相互转换,看官在进行实现时需要慢慢整理数据的类型,其思路上文已经给出。

笔者之前在culcon()方法实现时犯了一个错误,就是把上述的公式延伸给记反了,导致后面结果出错,还有一点就是,这个方法有点绕,毕竟有好多个for循环,还有要说明的地方就是itertools.combinations(m, q),即可以创建一个迭代器,返回m(为数组)中所有长度为q的子序列,结果以元组的形式返回,返回的子序列中的项按输入m中的顺序排序,所以加了for循环之后,可以看作是生成了不包含m本身的m的真子集。最后运行得到最终结果。

笔者方法的特点是多种数据形式的转换,看官们一定要搞清楚sorted(),"".join(list())等数据转换的方法。不然很容易就迷糊了,哈哈。

运行结果如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/571384
推荐阅读
相关标签
  

闽ICP备14008679号