做者:算法
wuliong,OpenFEA分析师。海归硕士,毕业于美国Rensselaer Polytechnic Institute数学专业。app
————————————————————————————————————————————————函数
Apriori算法是一种寻找频繁项集并在此基础上生成关联规则的算法。其本质是逐层搜索的迭代方法,且每次搜索分为生成候选集与检验支持度两个阶段。这种算法简单易懂、易于实现,是数据挖掘领域的经典算法之一。布局
Apriori算法应用普遍,可在产品目录设计、向上销售、商品陈列布局、根据消费行为对顾客细分等典型商业问题上为决策提供支持(本文不讨论如何产生关联规则,仅对寻找频繁项集的基本概念和计算步骤作介绍)。ui
为方便解释名词,咱们先引入一个应用场景:.net
1、应用场景及基本概念设计
假设某个淘宝店一上午有八个订单,交易明细以下:get
订单号 订单内容数学
001 (1,2,5)产品
002 (2,4)
003 (2,3)
004 (1,2,4)
005 (1,3)
006 (2,3)
007 (1,2,3,5)
008 (1,2,3)
咱们把这个包括所有交易细节的表格称为数据集(简称D),每一行对应一条交易记录(transaction,简称T)。交易记录里的数字是商品代码,由若干商品代码组成的集合称为项集(itemset),好比{1,3},包含k项商品代码的项集称为k项集,项集不能够为空(即k>0)。
随意选择一个项集,例如{1,3},经过查看数据集,咱们发现这个项集出如今三条交易记录中,即
{1,3},
{1,2,3,5}
{1,2,3}
除以交易记录总数8,咱们说这个项集的支持度(support)为37.5%。
若是设定最小支持度阈值为25%,凡支持度大于25%的项集均可以称为频繁项集(large itemset,简称L)。
算法的目的就是寻找全部符合条件(即大于支持度阈值)的频繁项集。写成数学表达式的话,算法的最终计算结果应是
U_{k}Lk
其中,Lk指全部包含k项的频繁项集所组成的集合, U_{k}指对全部Lk的并集。
2、算法基本步骤
寻找L1很是容易,只需扫描数据集并计算每一个商品代码出现的次数,选择那些支持度高于阈值的便可获得L1。
可是如何找出L2,L3,...呢?
提出Apriori算法的两位做者用一句简短明了的话描述了算法的核心思想, "The basic intuition is that any subset of a larget itemset must be large"(一个频繁项集的任意一个子集必然也是频繁项集)。
举例来讲,若是{1,3}是频繁项集,则它的全部子集(即{1}和{3})必然都是频繁项集。这句话暗示了自下至上搜索频繁项集的可能性,由于咱们知道,任何一个集合,必然与它的部分子集的并集相同。举例来讲,即使咱们事先不知道{1,3}属于频繁项集,可是因为{1}和{3}都属于频繁项集,若是计算L1中任意两个频繁项集的并集,则结果中必然包括{1,3}。这种经过对任意两个(k-1)项频繁项集求并集所获得的结果,咱们称之为k项候选集(Candidate,简称Ck)。候选集Ck包含了全部k项频繁项集,以及许多非频繁项集。对候选集Ck去粗取精,方能获得Lk。
从候选集中删除非频繁项集的方法有两种,第一种方法简单粗暴,即机械地计算每一个项集的支持度,再删除那些支持度低于阈值的项集。另外一种方法则是基于前面提到过的算法做者的话,一个频繁项集的子集必然也是频繁项集,反之,若是一个项集的某个子集不是频繁项集,则它自己也不多是频繁项集。显而易见,后一种方法计算量小,于是会优先使用,而前一种方法虽然计算量大可是能够准确的找出全部非频繁项集,故而也会使用。
此外,值得注意的是,在构建候选集Ck的过程当中,若是只是机械地对L(k-1)中的集合两两求并集,则任何一个k项频繁项集均可能会在Ck中出现屡次(准确说是k*(k-1)/2次,当k>2时,该表达式大于1)。
举例来讲,{1,2,3}会在C3中出现3次,由于它既是{1,2}和{2,3}的并集,也是{1,2}和{1,3},{1,3}和{2,3}的并集。若是咱们在构建Ck的过程当中增长一些限制条件,就能够避免重复减小计算量。
好比考虑下面这种特殊状况:假定A是一个k项频繁项集,则刚好有一个k-1项子集B1包括A的1...k-1项,又刚好有另外一个子集B2包含A的1...k-2项和第k项,B1和B2都属于L(k-1)而且它们的前k-2项相同。若是在构建Ck的过程当中,要求仅对前k-2项相同的两个集合求并集,则任何一个k项频繁项集在候选集中出现的次数正好是一次。固然,只有当k大于2时,咱们才须要用到这个限制条件。
上述方法构成了Apriori算法的骨干,下面就结合前文提到的淘宝订单例子详细介绍算法的基本步骤。
步骤1:
寻找只含1项的频繁项集L1。如前所述,需扫描数据集并计算各个商品代码出现次数,获得支持度(为方便讨论,此处支持度采用次数而非百分比):
{1},支持度=5
{2},支持度=7
{3},支持度=5
{4},支持度=2
{5},支持度=2
步骤2:
删除支持度不高于阈值(2次)的,获得L1={{1},{2},{3}}
步骤3:
已知L(k-1),寻找k项频繁项集Lk (k>=2)。
当k=2时,因为L1={{1},{2},{3}},很容易获得候选集C2={{1,2},{2,3},{1,3}}。
步骤4:
进一步计算C2中每一个项集的支持度分别为4,4和3,都高于阈值,因此L2={{1,2},{2,3},{1,3}}
当k=3时,已知L2={{1,2},{2,3},{1,3}},而且注意到只有{1,2}和{1,3}有类似的前k-2项(即第一项都为1),因此C3只需包括它们俩的并集即{1,2,3},而且考虑到{1,2,3}的全部子集都在L2中,因此它能够成为候选集,也就是说,C3={{1,2,3}}。计算这个惟一的候选项集的支持度,获得2,没有超过阈值,因此L3为空集。
由于L3为空,天然没法计算候选集C4甚至L4,因此计算过程到这里就结束了。而咱们要找的频繁项集为L={{1},{2},{3},{1,2},{2,3},{1,3}}
这样的计算,虽然不难,但操做起来比较繁琐。所幸FEA已经实现了这个算法,咱们只需对数据进行简单的处理,剩下的工做FEA会替您完成!
3、FEA寻找频繁项集的步骤
结合上文这个例子,下面手把手教您如何使用FEA寻找频繁项集,读者可在茶余饭后亲自尝试。
首先,作好数据导入的基础工做
导入数据,既能够经过导入csv文件,也能够手动建立:
a = @udf df0@sys by udf0.df_append with (1,1:2:5)
a = @udf a by udf0.df_append2 with (1,2:4)
…
a = @udf a by udf0.df_append2 with (8,1:2:3)
而且重命名列
rename a as (0:’tid’,1:’items’)
接着,将列类型转换为list:
a.items = str items by (split(‘:’))
而后,使用现成的函数寻找频繁项集:
a = @udf a by ML.fp_growth with (items,3)
这里参数取3,则全部支持度大于等于3的项集都会包含在结果中。
一步就查找完频繁项集
最后,dump a 查看查找结果
items support
1 5
2,1 4
3 5
1,3 3
2,3 4
2 7
第一列显示每一个频繁项集所包含的项,第二列显示该项集的支持度即它在数据集中出现次数。对于这个结果,咱们能够作进一步挖掘分析、寻找关联规律,限于篇幅有限此处不作展开。
读完此篇,你有没有感受到利用FEA寻找出频繁项集,简单不少?