本篇分为三个部分:

一、算法背景

啤酒与尿布故事:

某超市为增加销售量,提取出了他们超市所有的销售记录进行分析。在对这些小票数据进行分析时,发现男性顾客在购买婴儿尿片时,通常会顺便搭配带打啤酒来犒劳自己,于是超市就想如果把这两种平时看不出有关联的商品摆在一起,是不是能方便顾客同时提升商品的销量。于是尝试将啤酒和尿布摆在一起的上柜策略,最后果然两样商品的销量双双提升。

聪明的现代店家(甩饼)故事:

甩饼是2020年的一个店家,他听了啤酒与尿布故事后在想能不能有种便捷的方法可以找出这些有关联商品。比如说,客人完成购买行为后,客人会有小票。店家会有相应的购买记录(客人一次购买行为,购买了什么物品)。那么甩饼就可以利用这些购买记录来进行分析!举个栗子

比如客人,小敏去甩饼超市买泡面,小敏饭量大,一桶面不够吃,两桶又吃不了,她就在想那就加个蛋吧?还不够!那再来根香肠!

其他很多客人都会有小敏这样的购物习惯

所以,泡面、卤蛋、香肠就极大可能成组合,出现在每张小票上。

通过看小票有哪些商品经常成组合出现,则它们极大可能是关联商品。

支持度:

甩饼要怎么通过这些小票记录找出这些关联商品呢?于是他学习了Apriori算法。Apriori算法认为,如果某一组商品组合在所有小票中出现的次数太少,那么我们就认这组的商品之间没有什么关联(例如:A是头孢、B是白酒,那么A和B基本上不可能同时出现在同一张小票上,那么可以推断出他们没有什么关联)

那么甩饼又在想,要这组商品组合要出现在少于多少张小票,我们就可以认为它里面的商品是无关联的呢?

这个次数可以任意规定,我们可以把小票的张数称为支持度。这个支持度不宜太大也不宜太小,如果这个支持度太大,那么很多商品本来有关联(比如方便面和火腿),结果因为支持度定太大,就只能认为他们无关联了(比如说有一百张小票,你非得要求一百张小票都要有方便面和火腿,才认为它们有关联)。那如果定的支持度太小,那么很多无关联的商品(比如头孢和酒)又太容易被看错成有关联(比如说有一百张小票,你只要求有一张小票同时出现头孢和酒,你就认为它们有关联)

所以这个值取值一定得合适,这个合适的支持度取值我们就称之为最小支持度(商品组合出现的小票张数多于这个值,这组商品就有关。如果低于这个值,这组商品就无关)

那么甩饼有了购买记录(客人购买的小票),选取好一个最小支持度。对于特定的商品组合,他只需看这组商品组合在小票同时出现的支持度(次数)是不是大于这个最小支持度就可以判断,这组商品是否有关联(有这组商品组合的小票张数是不是大于最小支持度)

举个栗子:

商店里有5种商品,今天开出了4张小票,每行对应一张小票(为了方便起见,把ABCDE换成数字 1 2 3 4 5):

[A C D] --> 1 3 4

[B C E] --> 2 3 5

[A B C E] --> 1 2 3 5

[B E] --> 2 5

这时A在三张小票中出现,那么A的支持度support(A)=3

AC商品组合在同样三张小票中出现,那么AC组合的支持度support(AC)=3

如果甩饼选择最小支持度min_support=2,那么即可认为商品组合支持度大于最小支持度的组内商品是有关联的

所以support(AC)>min_support 则A、C可认为有关联

二、算法介绍

先介绍两个定律:

Apriori定律1 :如果某商品组合小于最小支持度,则就将它舍去,它的超集必然不是频繁项集。

Apriori定律2 :如果一个集合是频繁项集,即这个商品组合支持度大于最小支持度,则它的所有子集都是频繁项集

为了方便对两个定律的理解,还是用之前的小票数据,分别举例说明:

[A C D] --> 1 3 4

[B C E] --> 2 3 5

[A B C E] --> 1 2 3 5

[B E] --> 2 5

1° 对于Apriori定律1,对于BC这个商品组合,它出现的次数为1,即support(BC)=1

2° 对于Apriori定律2,基于Apriori定律1的很容易理解Apriori定律2。若AC的支持度大于2,那么A的支持度必大于2(AC都出现3次了,A当然也至少出现3次)

算法实现思路:

1、从一个商品开始找,找出所有的频繁项集(就是该商品的支持度大于最小支持度)

2、根据频繁项集确认下一组候选集

3、从候选集筛选频繁项集,从而递归步骤2、步骤3 ,直到不能递归为止

过程如图所示:

(1)第一次扫描

首先,求第一次扫描数据库后的候选集。

从图中可以看出,第一次扫描后,可以求出单个商品的支持度(图中支持度用出现次数表示),这个表称为第一次候选集,即下图所示:

在第一次候选集基础上,求出第一次频繁项集,频繁项就是该商品的支持度 大于 最小支持度,支持度选择时随意的,在这里取最小支持度为 min_support=2

那么第一次频繁项集就是第一次候选集中,支持度大于或大于2的所有商品集合。即下表,(把 D 商品从表中去除了,因为它的支持度小于2)

(2)第二次扫描

先求出第二次的候选集。

即在第一次频繁项集的基础上,找出第二次候选集,对商品进行组合,形成一个2元组,4种商品,不同组合有C42种,即 4x3=12 种,形成的表称为第二次候选集表。如下图

在求第二次频繁项集

对于上表,求出这两种商品同时出现在总记录中的次数(即求支持度),然后去掉支持度小于2的商品组合,形成的表即为第二次频繁项集。如下表

(3)第三次扫描

先求出第三次的候选集。

即在第二次频繁项集的基础上,找出第三次候选集。

就是将原来的2元组,拓展为3元组,怎么拓展呢?

设K为第K次扫描,要求第K个候选集,找出上一次扫描的频繁项集,然后观察里面的记录,对于里面的每个记录,前(K-2)个前缀相同的,归为一类,在同一类别中进行合并。

比如 这第三次扫描,要求出它的候选集,先找出上次扫描形成的第二次频繁项集表,里面有4条记录,分别为,AC,BC,BE,CE,这些记录中,前(K-2)个前缀,就是前(3-2)个前缀,也就是第一个前缀相同的归为一类,接着在属于同一类的记录中,进行合并,比如BC,BE,它门的第一个前缀都是B,那么在这一类中,把它门合并起来就形成了BCE。还剩下AC、CE,它门第一个前缀不相同,也没有其他元素和它门相同,那么就不用去管了。如果你非要合并,把AC、CE合并为ACE,我们看一下ACE的子集,它的子集是{AC、CE、AE},可以看出AC、CE确实是频繁项集,但是AE呢,你在求第二次的候选集时,因为AE的支持度小于2,你把它去除了,那么ACE也必然不是频繁项集。(Apriori定律1 :如果某商品组合小于最小支持度,则就将它舍去,它的超集必然不是频繁项集。)

减枝的概念:

比如刚才新形成的BCE这个组合,它的子集是{BC、CE、BE},显然BC和CE本来就是一个频繁项集,但是CE呢,我们必须对比上一次频繁项集中的元素,也就是第2次频繁项集的元素,如果CE不是第二次频繁项集的元素,那么就把新形成的 BC E 这个元素给 “减去”,也就是减枝,这一点我在代码中有体现,具体请看后面的代码。

(4)第四次扫描和前两次原理,一样,留给读者做练习。

最后值得一提的是,当最后生成的候选集表中,只有0个或1个的话,循环就结束了。

三、python代码实现

代码输出如下:

代码如下:

'''#请从最后的main方法开始看起

Apriori算法,频繁项集算法

A 1, B 2, C 3, D 4, E 5

1 [A C D] 1 3 4

2 [B C E] 2 3 5

3 [A B C E] 1 2 3 5

4 [B E] 2 5

min_support = 2 或 = 2/4'''

def item(dataset): #求第一次扫描数据库后的 候选集,(它没法加入循环)

c1 = [] #存放候选集元素

for x in dataset: #就是求这个数据库中出现了几个元素,然后返回

for y inx:if [y] not inc1:

c1.append( [y] )

c1.sort()#print(c1)

returnc1defget_frequent_item(dataset, c, min_support):

cut_branch= {} #用来存放所有项集的支持度的字典

for x inc:for y indataset:if set(x).issubset(set(y)): #如果 x 在 y中,就把对应元素后面加 1

cut_branch[tuple(x)] = cut_branch.get(tuple(x), 0) + 1 #cut_branch[y] = new_cand.get(y, 0)表示如果字典里面没有想要的关键词,就返回0

#print(cut_branch)

Fk= [] #支持度大于最小支持度的项集, 即频繁项集

sup_dataK = {} #用来存放所有 频繁 项集的支持度的字典

for i incut_branch:if cut_branch[i] >= min_support: #Apriori定律1 小于支持度,则就将它舍去,它的超集必然不是频繁项集

Fk.append( list(i))

sup_dataK[i]=cut_branch[i]#print(Fk)

returnFk, sup_dataKdef get_candidate(Fk, K): #求第k次候选集

ck = [] #存放产生候选集

for i inrange(len(Fk)):for j in range(i+1, len(Fk)):

L1= list(Fk[i])[:K-2]

L2= list(Fk[j])[:K-2]

L1.sort()

L2.sort()#先排序,在进行组合

if L1 ==L2:if K > 2: #第二次求候选集,不需要进行减枝,因为第一次候选集都是单元素,且已经减枝了,组合为双元素肯定不会出现不满足支持度的元素

new = list(set(Fk[i]) ^ set(Fk[j]) ) #集合运算 对称差集 ^ (含义,集合的元素在t或s中,但不会同时出现在二者中)

#new表示,这两个记录中,不同的元素集合

#为什么要用new? 比如 1,2 1,3 两个合并成 1,2,3 我们知道1,2 和 1,3 一定是频繁项集,但 2,3呢,我们要判断2,3是否为频繁项集

#Apriori定律1 如果一个集合不是频繁项集,则它的所有超集都不是频繁项集

else:

new=set()for x inFk:if set(new).issubset(set(x)) and list(set(Fk[i]) | set(Fk[j])) not in ck: #减枝 new是 x 的子集,并且 还没有加入 ck 中

ck.append( list(set(Fk[i]) |set(Fk[j])) )#print(ck)

returnckdef Apriori(dataset, min_support = 2):

c1= item (dataset) #返回一个二维列表,里面的每一个一维列表,都是第一次候选集的元素

f1, sup_1 = get_frequent_item(dataset, c1, min_support) #求第一次候选集

F= [f1] #将第一次候选集产生的频繁项集放入 F ,以后每次扫描产生的所有频繁项集都放入里面

sup_data = sup_1 #一个字典,里面存放所有产生的候选集,及其支持度

K= 2 #从第二个开始循环求解,先求候选集,在求频繁项集

while (len(F[K-2]) > 1): #k-2是因为F是从0开始数的 #前一个的频繁项集个数在2个或2个以上,才继续循环,否则退出

ck = get_candidate(F[K-2], K) #求第k次候选集

fk, sup_k = get_frequent_item(dataset, ck, min_support) #求第k次频繁项集

F.append(fk)#把新产生的候选集假如F

sup_data.update(sup_k) #字典更新,加入新得出的数据

K+=1

return F, sup_data #返回所有频繁项集, 以及存放频繁项集支持度的字典

if __name__ == '__main__':

dataset= [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] #装入数据 二维列表

F, sup_data = Apriori(dataset, min_support = 2) #最小支持度设置为2

print("具有关联的商品是{}".format(F)) #带变量的字符串输出,必须为字典符号表示

print('------------------')print("对应的支持度为{}".format(sup_data))

博文内容改自:https://blog.csdn.net/qq_39872846/article/details/105291265

apriori算法python代码_通俗易懂Apriori算法及Python实现相关推荐

  1. latex附录中放python代码_在Latex中插入Python代码

    这里指的插入是指最终能在生成的pdf中显示高亮的Python代码. 在Latex中插入Python代码,需要一个第三发的宏包pythonhighlight: https://github.com/ol ...

  2. 人工鱼群算法python代码_人工鱼群算法python_鱼群算法 - Brillou的个人空间 - OSCHINA - 中文开源技术交流社区......

    本算法是参照李晓磊博士的论文实现的,详细的算法原理可阅读<一种新型的智能优化方法_人工鱼群算法_李晓磊> 算法基于鱼群的生存行为:在一片水域中,鱼存在的数目最多的地方就是本水域中富含营养物 ...

  3. a*算法matlab代码_导向滤波算法及其matlab代码实现

    导向滤波同样是一种平滑滤波算法,其与最小二乘滤波和双边滤波相比,同样是一种具有边缘保持的功能的图形滤波算法,可以用于处理图形噪点较多的图像,而且此种滤波算法与最小二乘滤波和双边滤波相比,有其独特的特点 ...

  4. python代码_如何使用 Sphinx 给 Python 代码写文档

    最好将文档作为开发过程的一部分.Sphinx 加上 Tox,让文档可以轻松书写,并且外观漂亮.-- Moshe Zadka(作者) Python 代码可以在源码中包含文档.这种方式默认依靠 docst ...

  5. 20个python代码_有用的20个python代码段(4)

    有用的20个python代码段(4): 1.使用列举获取索引和值对 以下脚本使用列举来迭代列表中的值及其索引.my_list = ['a', 'b', 'c', 'd', 'e'] for index ...

  6. sublime运行python代码_怎么用sublime运行python

    首先需要安装一个Sublime Text(http://www.sublimetext.com/)和一个Python(https://www.python.org/downloads/) 接下来打开S ...

  7. 如何读懂python代码_教你如何阅读 Python 开源项目代码

    作者: Destiny 来源:https://learnku.com/articles/23010/teach-you-to-read-the-python-open-source-project-c ...

  8. 中文分词算法python代码_中文分词算法之最大正向匹配算法(Python版)

    最大匹配算法是自然语言处理中的中文匹配算法中最基础的算法,分为正向和逆向,原理都是一样的. 正向最大匹配算法,故名思意,从左向右扫描寻找词的最大匹配. 首先我们可以规定一个词的最大长度,每次扫描的时候 ...

  9. 正向最大匹配算法 python代码_中文分词算法之最大正向匹配算法(Python版)

    最大匹配算法是自然语言处理中的中文匹配算法中最基础的算法,分为正向和逆向,原理都是一样的. 正向最大匹配算法,故名思意,从左向右扫描寻找词的最大匹配. 首先我们可以规定一个词的最大长度,每次扫描的时候 ...

最新文章

  1. python if elif else 区别
  2. 关于 Delphi 中流的使用(6) 用流读写结构化文件
  3. Nginx下安装配置PageSpeed模块,轻松完成网站提速
  4. android 官方DrawerLayout的介绍和使用
  5. 2022.3.25黄花酢浆草
  6. .NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇
  7. linux read recv,read()/ recv()成功,但缓冲区未更改且为空
  8. web前端岗位经典面试题,面试前必读!
  9. MyFlash使用总结
  10. mysql optimizertrace_MySQL 调优 | OPTIMIZER_TRACE详解
  11. scrcpy设置快捷键_scrcpy——Android投屏神器(使用教程)
  12. pycharm下自建python包引入失败解决方案
  13. 计算机-库win10,Win10游戏运行库合集32/64位 官方最新版
  14. YOLOV5目标检测-后处理NMS(非极大值抑制)
  15. Linux FTP服务搭建(完整步骤)
  16. 微信支付接口 java服务器,JAVA微信支付接口开发——支付(示例代码)
  17. B站视频缓存 音频和视频批量合并
  18. 游戏文化VS文化游戏(第二篇)
  19. python爬虫:批量下载qq空间里的照片(二)
  20. Angular实现数据双向绑定

热门文章

  1. 如何绘制上证50指数,且基于历史收盘价计算出百分位数
  2. Go语学习笔记 - goroutine | 从零开始Go语言
  3. Python实现Canny算子
  4. 台计算机是怎么诞生的,第一台计算机是怎么诞生的?
  5. 关于for循环数据溢出问题
  6. android 静态链接libc,静态链接任何库会导致libc无法链接
  7. Blender学习笔记(建模#3:点操作)
  8. 实验室设计有哪些基本原则
  9. 电子开发工具箱-集成串口、网络等多个功能-E-Tool
  10. 【无人驾驶系列】光学雷达(LiDAR)在无人驾驶技术中的应用