热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

推荐系统实践(一)Apriori

关联规则之Apriori一、名词解释:支持度和置信度:支持度、置信度越大,商品出现一起购买的次数就越多,可信度就越大作用&

关联规则之Apriori

一、名词解释:
支持度和置信度:在这里插入图片描述
支持度、置信度越大,商品出现一起购买的次数就越多,可信度就越大
作用:找到商品购买记录中反复一起出现的商品,帮助营销人员做更好的策略,帮助顾客方便购买
策略:同时购买的商品放在一起、同时购买的商品放在两端
support(A->B) = P(AB)
confidence(A->B) = P(B|A)=P(AB)/P(A)
项集:项的集合,也就是商品的组合
K项集:K种商品的组合
频繁项集:如果项集的相对支持度满足给定的最小值支持度,则该项集是频繁项集
强关联规则:满足给定支持度与置信度阈值的关联规则

二、明确问题
明确问题:
1.找到总是一起出现的物品
2.提出衡量标准:支持度、置信度阈值
3.支持度、置信度计算
4.频繁项集
5.由频繁项集找到强管关联规则

找关联规则 --------> 频繁项集
1.找出所有的频繁项集:这个项集出现的次数至少与要求的最小计数一样
2.由频繁项集产生强关联规则:这些关联规则满足最小支持度与最小置信度

挑战:
1.多次数据库扫描
2.巨大数量的候补项集
3.繁琐的支持度计算

改善:
1.减少数据库扫描次数
2.减少候选项集的数量,提高支持度
3.简化候选项集的支持度计算

三、过程,原理:

产生频繁集:
Apriori 的原理:如果某个项集是频繁项集,那么它所有的子集也是频繁的。
即如果 {0,1} 是频繁的,那么 {0}, {1} 也一定是频繁的。

生关联规则:
从一个频繁项集可以产生多少条关联规则呢?可以基于该频繁项集生成一个可能的规则列表,然后测试每条规则的可信度,如果可信度不满足最小值要求,则去掉该规则。类似于前面讨论的频繁项集生成,一个频繁项集可以产生许多可能的关联规则,如果能在计算规则可信度之前就减少规则的数目,就会很好的提高计算效率。
这里有一条规律就是:如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求,

算法流程:
下面我们对Aprior算法流程做一个总结。

输入:数据集合D,支持度阈值α
    输出:最大的频繁k项集

1)扫描整个数据集,得到所有出现过的数据,作为候选频繁1项集。k=1,频繁0项集为空集。
2)挖掘频繁k项集

a) 扫描数据计算候选频繁k项集的支持度

b) 去除候选频繁k项集中支持度低于阈值的数据集,得到频繁k项集。如果得到的频繁k项集为空,则直接返回频繁k-1项集的集合作为算法结果,算法结束。如果得到的频繁k项集只有一项,则直接返回频繁k项集的集合作为算法结果,算法结束。

c) 基于频繁k项集,连接生成候选频繁k+1项集。

3) 令k=k+1,转入步骤2。

从算法的步骤可以看出,Aprior算法每轮迭代都要扫描数据集,因此在数据集很大,数据种类很多的时候,算法效率很低。

四、代码解析:
(1)主函数入口

if __name__ == '__main__':myDat = LoadDataSet() # 导入数据集L, suppData = apriori(myDat, 0.5) # 选择频繁项集print(u"频繁项集L:", L)print(u"所有候选项集的支持度信息:", suppData)rules = generateRules(L, suppData, minConf=0.7)print('rules:\n', rules)

dataSet数据人为设定

# 生成原始数据集用于测试
def LoadDataSet():return [[1, 3, 4, 5], [2, 3, 5], [1, 2, 3, 4, 5], [2, 3, 4, 5]]

(2)分析第一部分,对频繁集的求解。首先,调用CreateC1(),求解dataSet中有多少不同的值;再用scanD()用阈值minSupport去过滤频繁项集;

# 输入:数据集、最小支持度
def apriori(dataSet, minSupport=0.5):C1 = CreateC1(dataSet) # 构建初始候选项集C1D = [set(var) for var in dataSet] #对数据及进行映射至D, 去掉重复的数据记录L1, suppData = scanD(D, C1, minSupport) # 构建初始的频繁项集,即所有项集只有一个元素L = [L1] # 最初的L1中的每个项集含有一个元素,新生成的k = 2 # 项集应该含有2个元素,所以 k=2# 根据L1寻找L2、L3,通过while来完成# 他创建包含更大项集的更大列表,直到下一个更大的项集为空# 候选项集物品组合长度不超过元数据集原数据集最大的物品记录长度# 如果原始数据集物品记录最大长度为4,候选集最多为4项集while (len(L[k - 2]) > 0): #如果前面的前面的频繁项集合为空,则停止迭代Ck = aprioriGen(L[k - 2], k) # 生成候选集合 如果输入为{0}, {1}, {2}, 会生成 {0,1}, {0,2}, {1,2}Lk, supK = scanD(D, Ck, minSupport)suppData.update(supK) # 将新的项集的支持度数据加入原来的总支持度字典中L.append(Lk) # 将符合最小支持度要求的项集加入Lk += 1 # 新生成的项集中的元素个数应不断增加return L, suppData # 返回所有满足条件的频繁项集的列表,和所有候选项集的支持度信息

CreateC1(): 求解dataSet中有多少不同的值

# 遍历数据集每项物品,建立1-项集
def CreateC1(dataSet):'''构建初始候选项集的列表,即所有候选项集只包含一个元素,C1是大小为1的所有候选项集的集合'''C1 = []for transaction in dataSet:for item in transaction:if [item] not in C1:C1.append([item])C1.sort() #print("C1 : " + str(C1)) #输出[[1],[2],[3],[4],[5]]return [frozenset(var) for var in C1] # frozenset数据类型,不能被修改 只有var是数组的时候才能够frezenset(var)#print([var for var in map(frozenset,C1)]) #得到[frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]# print([var for var in map(frozenset,C1)])

scanD()求解支持度,用阈值minSupport去过滤频繁项集。

# 输入:数据集D, 候选集CK, 最小支持度
# 候选集Ck由上一层的频繁项集Lk-1组合得到
# 用最小支持度minSupport对候选集Ck过滤
# 输出:第k层的频繁项集Lk,每项的支持度
def scanD(D, Ck, minSupport):'''计算Ck中的项集在数据集合D(记录或者transactions)中的支持度,返回满足最小支持度的项集的集合,和所有项集支持度信息的字典。'''# 建立字典,key为候选集Ck中的每项, value为该物品在所有物品记录中出现的次数ssCnt = {}# 对比候选集中的每项与原物品记录,统计出现的次数# 遍历每条物品记录for tid in D: # 对于每一条transactionfor can in Ck: # 对于每一个候选项集can,检查是否是transaction的一部分 # 即该候选can是否得到transaction的支持if can.issubset(tid):ssCnt[can] = ssCnt.get(can, 0) + 1 #get() 函数返回指定键的值,如果值不在字典中返回默认值。numItems = float(len(D)) # 数据集中总的记录数,物品购买记录总数,用于计算支持度retList = [] # 记录经最小支持度过滤后的频繁项集# key ---------> 候选集中满足条件的项# value -------> 该项支持度supportData = {}for key in ssCnt:support = ssCnt[key] / numItems # 每个项集的支持度if support >= minSupport: # 将满足最小支持度的项集,加入retListretList.insert(0, key)supportData[key] = support # 记录该项的支持度return retList, supportData

aprioriGen() :生成候选集合 如果输入为{0}, {1}, {2}, 会生成 {0,1}, {0,2}, {1,2}
选取候选集的时候有个方法:比较频繁项集中的每项与其他项,若两项的前k-1个元素相同,那么就将两项合并。这是由于apriori的算法原理的问题。

# 由上层频繁k-1项集生成候选k项集
# 如果输入为{0}, {1}, {2}, 会生成 {0,1}, {0,2}, {1,2}
# 输入:频繁k-1项集,新的候选集元素个数k
# 输出:候选集
def aprioriGen(Lk, k): # Aprior算法'''由初始候选项集的集合Lk生成新的生成候选项集,k表示生成的新项集中所含有的元素个数'''retList = [] # 保存新的候选集lenLk = len(Lk)# 比较频繁项集中的每项与其他项,若两项的前k-1个元素相同,那么就将两项合并for i in range(lenLk):for j in range(i + 1, lenLk):L1 = list(Lk[i])[: k - 2]# 候选集其余项的k-1个元素,每次只有其余项中的一项L2 = list(Lk[j])[: k - 2]L1.sort()L2.sort()if L1 == L2:# 相同,两项合并retList.append(Lk[i] | Lk[j])return retList #例如: Lk = [{A,C},{B,C},{B,E},{C,E}] 找有三个数的频繁集: Lk[1][:1] == 'B' ==Lk[2][:1] 所以retList = [{B,C,E}]

(3)生成关联规则:
主函数:generateRules():

这里有一条规律就是:如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求,
def generateRules(L, supportData, minConf=0.7):'''根据频繁项集和最小可信度生成规则。L(list):存储频繁项集supportData(dict):存储着所有项集(不仅仅是频繁项集)的支持度minConf(float):最小可信度'''bigRuleList = []for i in range(1, len(L)):for freqSet in L[i]: # 对于每一个频繁项集的集合freqSet,(从k=2开始)H1 = [frozenset([item]) for item in freqSet]if i > 1: # 如果频繁项集中的元素个数大于2,需要进一步合并,这样做的结果就是会有“[1|多]->多”(右边只会是“多”,# 因为合并的本质是频繁子项集变大,而calcConf函数的关联结果的右侧就是频繁子项集),的关联结果rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)else:calcConf(freqSet, H1, supportData, bigRuleList, minConf)return bigRuleList

计算置信度:calcConf()

def calcConf(freqSet, H, supportData, brl, minConf=0.7): # 规则生成与评价'''计算规则的可信度,返回满足最小可信度的规则。freqSet(frozenset):频繁项集H(frozenset):频繁项集中所有的元素supportData(dic):频繁项集中所有元素的支持度brl(tuple):满足可信度条件的关联规则minConf(float):最小可信度'''prunedH = []for conseq in H:conf = supportData[freqSet] / supportData[freqSet - conseq]if conf >= minConf:print(freqSet - conseq, '-->', conseq, 'conf:', conf)brl.append((freqSet - conseq, conseq, conf))prunedH.append(conseq)return prunedH

rulesFromConseq():# 如果频繁项集中的元素个数大于2,需要进一步合并,这样做的结果就是会有“[1|多]->多”(右边只会是“多”,# 因为合并的本质是频繁子项集变大,而calcConf函数的关联结果的右侧就是频繁子项集),的关联结果

def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):'''对频繁项集中元素超过2的项集进行合并。freqSet(frozenset):频繁项集H(frozenset):频繁项集中的所有元素,即可以出现在规则右部的元素supportData(dict):所有项集的支持度信息brl(tuple):生成的规则'''m = len(H[0])if len(freqSet) > m + 1: # 查看频繁项集是否足够大,以到于移除大小为 m的子集,否则继续生成m+1大小的频繁项集Hmp1 = aprioriGen(H, m + 1)Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf) # 对于新生成的m+1大小的频繁项集,计算新生成的关联规则的右则的集合if len(Hmp1) > 1: # 如果不止一条规则满足要求(新生成的关联规则的右则的集合的大小大于1),进一步递归合并,# 这样做的结果就是会有“[1|多]->多”(右边只会是“多”,因为合并的本质是频繁子项集变大,# 而calcConf函数的关联结果的右侧就是频繁子项集)的关联结果rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
author-avatar
手机用户2602916275
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有